From 0b4c29f6dcca0c74a3e0f002e8127b2ddc8fdc1e Mon Sep 17 00:00:00 2001 From: mehdihadeli Date: Thu, 21 Sep 2023 02:26:21 +0330 Subject: [PATCH 01/15] refactor: :recycle: integrate jaeger with OTLP --- Makefile | 7 + .../docker-compose.infrastructure.yaml | 58 +++-- .../docker-compose/monitoring/prometheus.yml | 10 - internal/pkg/go.mod | 76 ++++--- internal/pkg/go.sum | 199 ++++++++++++------ internal/pkg/gorm_postgres/db.go | 8 +- .../pkg/gorm_postgres/gorm_postgres_fx.go | 8 + internal/pkg/logger/zap/zap_logger.go | 10 +- internal/pkg/mongodb/mongo_fx.go | 6 +- internal/pkg/mongodb/mongodb.go | 15 +- .../pkg/otel/config/open_telemtry_options.go | 13 +- internal/pkg/otel/tracing/tracing.go | 60 ++++-- .../config/config.development.json | 6 +- .../config/config.test.json | 6 +- internal/services/catalog_read_service/go.mod | 64 +++--- internal/services/catalog_read_service/go.sum | 172 +++++++++------ .../config/config.development.json | 4 +- .../config/config.test.json | 4 +- .../services/catalog_write_service/go.mod | 66 +++--- .../services/catalog_write_service/go.sum | 178 ++++++++++------ .../internal/shared/app/app.go | 8 + .../config/config.development.json | 6 +- .../order_service/config/config.test.json | 6 +- internal/services/order_service/go.mod | 66 +++--- internal/services/order_service/go.sum | 176 ++++++++++------ scripts/update-dependencies.sh | 13 ++ 26 files changed, 817 insertions(+), 428 deletions(-) create mode 100644 scripts/update-dependencies.sh diff --git a/Makefile b/Makefile index ddd873f7..4be46890 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,13 @@ build: @./scripts/build.sh catalog_read_service @./scripts/build.sh order_service +.PHONY: update-dependencies +update-dependencies: + @./scripts/update-dependencies.sh pkg + @./scripts/update-dependencies.sh catalog_write_service + @./scripts/update-dependencies.sh catalog_read_service + @./scripts/update-dependencies.sh order_service + .PHONY: install-dependencies install-dependencies: @./scripts/install-dependencies.sh pkg diff --git a/deployments/docker-compose/docker-compose.infrastructure.yaml b/deployments/docker-compose/docker-compose.infrastructure.yaml index ca68fdd6..f2200e6d 100644 --- a/deployments/docker-compose/docker-compose.infrastructure.yaml +++ b/deployments/docker-compose/docker-compose.infrastructure.yaml @@ -144,15 +144,31 @@ services: networks: - ecommerce + # https://www.jaegertracing.io/docs/1.38/apis/#opentelemetry-protocol-stable + # https://deploy-preview-1892--opentelemetry.netlify.app/blog/2022/jaeger-native-otlp/ + # https://www.jaegertracing.io/docs/1.49/deployment/ + # https://www.jaegertracing.io/docs/1.49/getting-started/ + # https://opentelemetry.io/docs/instrumentation/go/exporters/ + # https://opentelemetry.io/docs/specs/otlp/ jaeger: + image: jaegertracing/all-in-one:latest container_name: jaeger pull_policy: if_not_present - restart: on-failure - image: jaegertracing/all-in-one:latest + environment: + - COLLECTOR_ZIPKIN_HOST_PORT=:9411 + - COLLECTOR_OTLP_ENABLED=true + - METRICS_STORAGE_TYPE=prometheus + - PROMETHEUS_SERVER_URL=http://prometheus:9090 ports: + - "6831:6831/udp" + - "6832:6832/udp" + - "5778:5778" - "16686:16686" - - "14268:14268" + - "4317:4317" + - "4318:4318" - "14250:14250" + - "14268:14268" + - "14269:14269" networks: - ecommerce @@ -166,24 +182,24 @@ services: networks: - ecommerce - otel-collector: - image: otel/opentelemetry-collector-contrib-dev:latest - pull_policy: if_not_present - command: ["--config=/etc/otel-collector-config.yaml", ""] - volumes: - - ./otel-collector-config.yaml:/etc/otel-collector-config.yaml - ports: - - "1888:1888" # pprof extension - - "8888:8888" # Prometheus metrics exposed by the collector - - "8889:8889" # Prometheus exporter metrics - - "13133:13133" # health_check extension - - "4317:4317" # OTLP gRPC receiver - - "55679:55679" # zpages extension - depends_on: - - jaeger - - zipkin - networks: - - ecommerce +# otel-collector: +# image: otel/opentelemetry-collector-contrib-dev:latest +# pull_policy: if_not_present +# command: ["--config=/etc/otel-collector-config.yaml", ""] +# volumes: +# - ./otel-collector-config.yaml:/etc/otel-collector-config.yaml +# ports: +# - "1888:1888" # pprof extension +# - "8888:8888" # Prometheus metrics exposed by the collector +# - "8889:8889" # Prometheus exporter metrics +# - "13133:13133" # health_check extension +# - "4317:4317" # OTLP gRPC receiver +# - "55679:55679" # zpages extension +# depends_on: +# - jaeger +# - zipkin +# networks: +# - ecommerce # https://developers.eventstore.com/server/v21.10/installation.html#insecure-single-node # https://hub.docker.com/r/eventstore/eventstore/tags diff --git a/deployments/docker-compose/monitoring/prometheus.yml b/deployments/docker-compose/monitoring/prometheus.yml index 3ed6cff7..7374ee79 100644 --- a/deployments/docker-compose/monitoring/prometheus.yml +++ b/deployments/docker-compose/monitoring/prometheus.yml @@ -7,10 +7,6 @@ scrape_configs: static_configs: - targets: [ 'localhost:9090' ] - - job_name: 'system' - static_configs: - - targets: [ 'host.docker.internal:9101' ] - - job_name: 'product_write_service' static_configs: - targets: [ 'host.docker.internal:8002' ] @@ -18,9 +14,3 @@ scrape_configs: - job_name: 'product_read_service' static_configs: - targets: [ 'host.docker.internal:8003' ] - - # - job_name: 'otel-collector' - # scrape_interval: 10s - # static_configs: - # - targets: ['otel-collector:8889'] - # - targets: ['otel-collector:8888'] \ No newline at end of file diff --git a/internal/pkg/go.mod b/internal/pkg/go.mod index ffb1bcb7..9d147d48 100644 --- a/internal/pkg/go.mod +++ b/internal/pkg/go.mod @@ -11,12 +11,13 @@ require ( github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de github.com/avast/retry-go v3.0.0+incompatible github.com/caarlos0/env/v8 v8.0.0 - github.com/docker/docker v24.0.5+incompatible + github.com/docker/docker v24.0.6+incompatible github.com/docker/go-connections v0.4.0 github.com/doug-martin/goqu/v9 v9.18.0 - github.com/elastic/go-elasticsearch/v8 v8.9.0 + github.com/elastic/go-elasticsearch/v8 v8.10.0 github.com/go-playground/validator v9.31.0+incompatible - github.com/go-resty/resty/v2 v2.7.0 + github.com/go-redis/redis v6.15.9+incompatible + github.com/go-resty/resty/v2 v2.8.0 github.com/go-testfixtures/testfixtures/v3 v3.9.0 github.com/goccy/go-json v0.10.2 github.com/goccy/go-reflect v1.2.0 @@ -44,54 +45,58 @@ require ( github.com/prometheus/client_golang v1.16.0 github.com/rabbitmq/amqp091-go v1.8.1 github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 - github.com/redis/go-redis/v9 v9.0.5 + github.com/redis/go-redis/v9 v9.2.0 github.com/samber/lo v1.38.1 github.com/satori/go.uuid v1.2.0 github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.16.0 github.com/stretchr/testify v1.8.4 - github.com/testcontainers/testcontainers-go v0.23.0 - github.com/testcontainers/testcontainers-go/modules/postgres v0.23.0 - github.com/uptrace/bun v1.1.14 - github.com/uptrace/bun/dialect/pgdialect v1.1.14 - github.com/uptrace/bun/driver/pgdriver v1.1.14 + github.com/testcontainers/testcontainers-go v0.24.1 + github.com/testcontainers/testcontainers-go/modules/postgres v0.24.1 + github.com/uptrace/bun v1.1.16 + github.com/uptrace/bun/dialect/pgdialect v1.1.16 + github.com/uptrace/bun/driver/pgdriver v1.1.16 + github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 go.mongodb.org/mongo-driver v1.12.1 - go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.43.0 - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0 - go.opentelemetry.io/contrib/propagators/ot v1.18.0 - go.opentelemetry.io/otel v1.17.0 - go.opentelemetry.io/otel/exporters/jaeger v1.17.0 - go.opentelemetry.io/otel/exporters/prometheus v0.40.0 - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.17.0 - go.opentelemetry.io/otel/exporters/zipkin v1.17.0 - go.opentelemetry.io/otel/metric v1.17.0 - go.opentelemetry.io/otel/sdk v1.17.0 - go.opentelemetry.io/otel/sdk/metric v0.40.0 - go.opentelemetry.io/otel/trace v1.17.0 + go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 + go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 + go.opentelemetry.io/contrib/propagators/ot v1.19.0 + go.opentelemetry.io/otel v1.18.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 + go.opentelemetry.io/otel/exporters/prometheus v0.41.0 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 + go.opentelemetry.io/otel/exporters/zipkin v1.18.0 + go.opentelemetry.io/otel/metric v1.18.0 + go.opentelemetry.io/otel/sdk v1.18.0 + go.opentelemetry.io/otel/sdk/metric v0.41.0 + go.opentelemetry.io/otel/trace v1.18.0 go.uber.org/fx v1.20.0 - go.uber.org/zap v1.25.0 - google.golang.org/grpc v1.57.0 + go.uber.org/zap v1.26.0 + google.golang.org/grpc v1.58.1 gorm.io/driver/postgres v1.5.2 gorm.io/gorm v1.25.4 + gorm.io/plugin/opentelemetry v0.1.4 ) require ( dario.cat/mergo v1.0.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/ClickHouse/ch-go v0.58.2 // indirect - github.com/ClickHouse/clickhouse-go/v2 v2.13.4 // indirect + github.com/ClickHouse/clickhouse-go/v2 v2.14.1 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/hcsshim v0.11.0 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/andybalholm/brotli v1.0.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/containerd/containerd v1.7.5 // indirect + github.com/containerd/containerd v1.7.6 // indirect github.com/containerd/continuity v0.4.2 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/docker/cli v24.0.5+incompatible // indirect + github.com/docker/cli v24.0.6+incompatible // indirect github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/elastic/elastic-transport-go/v8 v8.3.0 // indirect @@ -101,6 +106,7 @@ require ( github.com/go-faster/errors v0.6.1 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -110,6 +116,7 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -125,11 +132,12 @@ require ( github.com/jackc/puddle v1.3.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - github.com/klauspost/compress v1.16.7 // indirect + github.com/klauspost/compress v1.17.0 // indirect github.com/labstack/gommon v0.4.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/leodido/go-urn v1.2.4 // indirect + github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect @@ -141,7 +149,7 @@ require ( github.com/morikuni/aec v1.0.0 // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc4 // indirect + github.com/opencontainers/image-spec v1.1.0-rc5 // indirect github.com/opencontainers/runc v1.1.9 // indirect github.com/openzipkin/zipkin-go v0.4.2 // indirect github.com/paulmach/orb v0.10.0 // indirect @@ -149,12 +157,15 @@ require ( github.com/pierrec/lz4/v4 v4.1.18 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.11.1 // indirect github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/segmentio/asm v1.2.0 // indirect + github.com/shirou/gopsutil/v3 v3.23.8 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/spf13/afero v1.9.5 // indirect github.com/spf13/cast v1.5.1 // indirect @@ -163,7 +174,10 @@ require ( github.com/streadway/amqp v1.1.0 // indirect github.com/stretchr/objx v0.5.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect + github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect @@ -175,6 +189,9 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect + go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/dig v1.17.0 // indirect go.uber.org/multierr v1.11.0 // indirect @@ -187,7 +204,8 @@ require ( golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/internal/pkg/go.sum b/internal/pkg/go.sum index fb555b42..7cfca3c0 100644 --- a/internal/pkg/go.sum +++ b/internal/pkg/go.sum @@ -25,8 +25,8 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= -cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= +cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -55,8 +55,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ClickHouse/ch-go v0.58.2 h1:jSm2szHbT9MCAB1rJ3WuCJqmGLi5UTjlNu+f530UTS0= github.com/ClickHouse/ch-go v0.58.2/go.mod h1:Ap/0bEmiLa14gYjCiRkYGbXvbe8vwdrfTYWhsuQ99aw= -github.com/ClickHouse/clickhouse-go/v2 v2.13.4 h1:NcvYN9ONZn3vlPMfQVUBSG5LKz+1y2wk4vaaz5QZXIg= -github.com/ClickHouse/clickhouse-go/v2 v2.13.4/go.mod h1:u1AUh8E0XqN1sU1EDzbiGLTI4KWOd+lOHimNSsdyJec= +github.com/ClickHouse/clickhouse-go/v2 v2.14.1 h1:5C2hhmZEGUVdy8CPpY3iPpfBv2kRbx5iOcflU49Rzws= +github.com/ClickHouse/clickhouse-go/v2 v2.14.1/go.mod h1:PHqbMvJTQ0EI4a1vJhmbmL/Ajr+Cin2O+WJjnYctJvg= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/EventStore/EventStore-Client-Go v1.0.2 h1:onM2TIInLhWUJwUQ/5a/8blNrrbhwrtm7Tpmg13ohiw= @@ -68,8 +68,8 @@ github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA4 github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek= -github.com/Microsoft/hcsshim v0.10.0-rc.8/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= +github.com/Microsoft/hcsshim v0.11.0 h1:7EFNIY4igHEXUdj1zXgAyU3fLc7QfOKHbkldRVTBdiM= +github.com/Microsoft/hcsshim v0.11.0/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4= @@ -87,10 +87,12 @@ github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao= github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= -github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/caarlos0/env/v8 v8.0.0 h1:POhxHhSpuxrLMIdvTGARuZqR4Jjm8AYmoi/JKlcScs0= github.com/caarlos0/env/v8 v8.0.0/go.mod h1:7K4wMY9bH0esiXSSHlfHLX5xKGQMnkH5Fk4TDSSSzfo= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= @@ -113,8 +115,8 @@ github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWH github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= -github.com/containerd/containerd v1.7.5 h1:i9T9XpAWMe11BHMN7pu1BZqOGjXaKTPyz2v+KYOZgkY= -github.com/containerd/containerd v1.7.5/go.mod h1:ieJNCSzASw2shSGYLHx8NAE7WsZ/gEigo5fQ78W5Zvw= +github.com/containerd/containerd v1.7.6 h1:oNAVsnhPoy4BTPQivLgTzI9Oleml9l/+eYIDYXRCYo8= +github.com/containerd/containerd v1.7.6/go.mod h1:SY6lrkkuJT40BVNO37tlYTSnKJnP5AXBc0fhx0q+TJ4= github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= @@ -140,12 +142,12 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dhui/dktest v0.3.16 h1:i6gq2YQEtcrjKbeJpBkWjE8MmLZPYllcjOFbTZuPDnw= github.com/dhui/dktest v0.3.16/go.mod h1:gYaA3LRmM8Z4vJl2MA0THIigJoZrwOansEOsp+kqxp0= -github.com/docker/cli v24.0.5+incompatible h1:WeBimjvS0eKdH4Ygx+ihVq1Q++xg36M/rMi4aXAvodc= -github.com/docker/cli v24.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY= +github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY= -github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE= +github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= @@ -159,16 +161,16 @@ github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+m github.com/elastic/elastic-transport-go/v8 v8.0.0-20230329154755-1a3c63de0db6/go.mod h1:87Tcz8IVNe6rVSLdBux1o/PEItLtyabHU3naC7IoqKI= github.com/elastic/elastic-transport-go/v8 v8.3.0 h1:DJGxovyQLXGr62e9nDMPSxRyWION0Bh6d9eCFBriiHo= github.com/elastic/elastic-transport-go/v8 v8.3.0/go.mod h1:87Tcz8IVNe6rVSLdBux1o/PEItLtyabHU3naC7IoqKI= -github.com/elastic/go-elasticsearch/v8 v8.9.0 h1:8xtmYjUkqtahl50E0Bg/wjKI7K63krJrrLipbNj/fCU= -github.com/elastic/go-elasticsearch/v8 v8.9.0/go.mod h1:NGmpvohKiRHXI0Sw4fuUGn6hYOmAXlyCphKpzVBiqDE= +github.com/elastic/go-elasticsearch/v8 v8.10.0 h1:ALg3DMxSrx07YmeMNcfPf7cFh1Ep2+Qa19EOXTbwr2k= +github.com/elastic/go-elasticsearch/v8 v8.10.0/go.mod h1:NGmpvohKiRHXI0Sw4fuUGn6hYOmAXlyCphKpzVBiqDE= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= -github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= @@ -192,14 +194,19 @@ github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator v9.31.0+incompatible h1:UA72EPEogEnq76ehGdEDp4Mit+3FDh548oRqwVgNsHA= github.com/go-playground/validator v9.31.0+incompatible/go.mod h1:yrEkQXlcI+PugkyDjY2bRrL/UBU4f3rvrgkN3V8JEig= -github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= -github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= +github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= +github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-resty/resty/v2 v2.8.0 h1:J29d0JFWwSWrDCysnOK/YjsPMLQTx0TvgJEHVGvf2L8= +github.com/go-resty/resty/v2 v2.8.0/go.mod h1:UCui0cMHekLrSntoMyofdSTaPpinlRHFtPpizuyDW2w= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= @@ -227,6 +234,8 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2V github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -302,6 +311,8 @@ github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e h1:XmA6L9IP github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e/go.mod h1:AFIo+02s+12CEg8Gzz9kzhCbmbq6JcKNrhHffCGA9z4= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -392,8 +403,8 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:C github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -425,6 +436,9 @@ github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a h1:N9zuLhTvBSRt0gWSiJswwQ2HqDmtX/ZCDJURnKUt1Ik= +github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= @@ -484,8 +498,8 @@ github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= -github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= +github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc95/go.mod h1:z+bZxa/+Tz/FmYVWkhUajJdzFeOqjc5vrqskhVyHGUM= github.com/opencontainers/runc v1.1.9 h1:XR0VIHTGce5eWPkaPesqTBrhW2yAcaraWfsEalNwQLM= @@ -516,6 +530,9 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/pressly/goose/v3 v3.15.0 h1:6tY5aDqFknY6VZkorFGgZtWygodZQxfmmEF4rqyJW9k= github.com/pressly/goose/v3 v3.15.0/go.mod h1:LlIo3zGccjb/YUgG+Svdb9Er14vefRdlDI7URCDrwYo= github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= @@ -534,8 +551,9 @@ github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJu github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc= github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ= github.com/redis/go-redis/v9 v9.0.3/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= -github.com/redis/go-redis/v9 v9.0.5 h1:CuQcn5HIEeK7BgElubPP8CGtE0KakrnbBSTLjathl5o= github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= +github.com/redis/go-redis/v9 v9.2.0 h1:zwMdX0A4eVzse46YN18QhuDiM4uf3JmkOB4VZrdt5uI= +github.com/redis/go-redis/v9 v9.2.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -556,6 +574,12 @@ github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7 github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= +github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= +github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= @@ -605,19 +629,27 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/testcontainers/testcontainers-go v0.23.0 h1:ERYTSikX01QczBLPZpqsETTBO7lInqEP349phDOVJVs= -github.com/testcontainers/testcontainers-go v0.23.0/go.mod h1:3gzuZfb7T9qfcH2pHpV4RLlWrPjeWNQah6XlYQ32c4I= -github.com/testcontainers/testcontainers-go/modules/postgres v0.23.0 h1:OEGUC1YTN1RyS4xqsHmlyYkBWm9lMJcswoV4JSHJQOM= -github.com/testcontainers/testcontainers-go/modules/postgres v0.23.0/go.mod h1:YnqIhPwhjqVbJBuvSRJS6pa9Cy1PDRJcrM6T63Uw2ms= +github.com/testcontainers/testcontainers-go v0.24.1 h1:gJdZuQIVWnMJTo+CmQMEP7/CAagNk/0jbcUPn3OWvD8= +github.com/testcontainers/testcontainers-go v0.24.1/go.mod h1:MGBiAkCm86yXQoCiipmQCqZLVdk1uFqtMqaU1Or0MRk= +github.com/testcontainers/testcontainers-go/modules/postgres v0.24.1 h1:lSJLORAjkj8PoiZef+KoziJbhpRmL1ELzJXQQ8L3s1U= +github.com/testcontainers/testcontainers-go/modules/postgres v0.24.1/go.mod h1:QG4rCYFma/K7CbAFtrqCIn87EI6bNRWaW+Ebt4UV2WA= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= -github.com/uptrace/bun v1.1.14 h1:S5vvNnjEynJ0CvnrBOD7MIRW7q/WbtvFXrdfy0lddAM= -github.com/uptrace/bun v1.1.14/go.mod h1:RHk6DrIisO62dv10pUOJCz5MphXThuOTpVNYEYv7NI8= -github.com/uptrace/bun/dialect/pgdialect v1.1.14 h1:b7+V1KDJPQSFYgkG/6YLXCl2uvwEY3kf/GSM7hTHRDY= -github.com/uptrace/bun/dialect/pgdialect v1.1.14/go.mod h1:v6YiaXmnKQ2FlhRD2c0ZfKd+QXH09pYn4H8ojaavkKk= -github.com/uptrace/bun/driver/pgdriver v1.1.14 h1:V2Etm7mLGS3mhx8ddxZcUnwZLX02Jmq9JTlo0sNVDhA= -github.com/uptrace/bun/driver/pgdriver v1.1.14/go.mod h1:D4FjWV9arDYct6sjMJhFoyU71SpllZRHXFRRP2Kd0Kw= +github.com/uptrace/bun v1.1.16 h1:cn9cgEMFwcyYRsQLfxCRMUxyK1WaHwOVrR3TvzEFZ/A= +github.com/uptrace/bun v1.1.16/go.mod h1:7HnsMRRvpLFUcquJxp22JO8PsWKpFQO/gNXqqsuGWg8= +github.com/uptrace/bun/dialect/pgdialect v1.1.16 h1:eUPZ+YCJ69BA+W1X1ZmpOJSkv1oYtinr0zCXf7zCo5g= +github.com/uptrace/bun/dialect/pgdialect v1.1.16/go.mod h1:KQjfx/r6JM0OXfbv0rFrxAbdkPD7idK8VitnjIV9fZI= +github.com/uptrace/bun/driver/pgdriver v1.1.16 h1:b/NiSXk6Ldw7KLfMLbOqIkm4odHd7QiNOCPLqPFJjK4= +github.com/uptrace/bun/driver/pgdriver v1.1.16/go.mod h1:Rmfbc+7lx1z/umjMyAxkOHK81LgnGj71XC5YpA6k1vU= +github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 h1:CNznWHkrbA6o1q2H/BsH4tIHf4zbKNtndeoV+AH8z0U= +github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2/go.mod h1:7YSrHCmYPHIXjTWnKSU7EGT0TFEcm3WwSeQquwCGg38= +github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 h1:uyrW06oJi4iWvhjPLVfk4qrSP2Zm0AMozKKDmp6i4pE= +github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2/go.mod h1:PMAs2dNxP55lgt6xu0if+Jasm6s+Xpmqn6ev1NyDfnI= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -657,6 +689,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY= go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= @@ -668,32 +702,38 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.43.0 h1:pcWR7mkuO5XMK3f0KeGpr70OTR9/ikPk0D1hHEd5dp4= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.43.0/go.mod h1:azTPpa9PvRDSNU/lQbe2CRDQoTcau5moOjS4EzhpyAY= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0 h1:7XZai4VhA473clBrOqqHdjHBImGfyEtv0qW4nnn/kAo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0/go.mod h1:1WpsUwjQrUJSNugfMlPn0rPRJ9Do7wwBgTBPK7MLiS4= -go.opentelemetry.io/contrib/propagators/b3 v1.18.0 h1:hhSlPVi9AQwOmbMmptPNLfRZOLgENdRM2kb7z9LFe1A= -go.opentelemetry.io/contrib/propagators/b3 v1.18.0/go.mod h1:qtt+pEu23D7UVP+j33G4i7LopmVu8/6/IwGu3hEm100= -go.opentelemetry.io/contrib/propagators/ot v1.18.0 h1:VmzxO7BjUU6oo0ChcKuGdKaSR0vchPxwahHZl64zVUM= -go.opentelemetry.io/contrib/propagators/ot v1.18.0/go.mod h1:5VwcOJ7OjS0uPxaxuwKHwJtkt+EAC+cgjXleXMe51z4= -go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM= -go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0= -go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4= -go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI= -go.opentelemetry.io/otel/exporters/prometheus v0.40.0 h1:9h6lCssr1j5aYVvWT6oc+ERB6R034zmsHjBRLyxrAR8= -go.opentelemetry.io/otel/exporters/prometheus v0.40.0/go.mod h1:5USWZ0ovyQB5CIM3IO3bGRSoDPMXiT3t+15gu8Zo9HQ= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.17.0 h1:Ut6hgtYcASHwCzRHkXEtSsM251cXJPW+Z9DyLwEn6iI= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.17.0/go.mod h1:TYeE+8d5CjrgBa0ZuRaDeMpIC1xZ7atg4g+nInjuSjc= -go.opentelemetry.io/otel/exporters/zipkin v1.17.0 h1:oi5+xMN3pflqWSd4EX6FiO+Cn3KbFBBzeQmD5LMIf0c= -go.opentelemetry.io/otel/exporters/zipkin v1.17.0/go.mod h1:pNir+S6/f0HFGfbXhobXLTFu60KtAzw8aGSUpt9A6VU= -go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc= -go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o= -go.opentelemetry.io/otel/sdk v1.17.0 h1:FLN2X66Ke/k5Sg3V623Q7h7nt3cHXaW1FOvKKrW0IpE= -go.opentelemetry.io/otel/sdk v1.17.0/go.mod h1:U87sE0f5vQB7hwUoW98pW5Rz4ZDuCFBZFNUBlSgmDFQ= -go.opentelemetry.io/otel/sdk/metric v0.40.0 h1:qOM29YaGcxipWjL5FzpyZDpCYrDREvX0mVlmXdOjCHU= -go.opentelemetry.io/otel/sdk/metric v0.40.0/go.mod h1:dWxHtdzdJvg+ciJUKLTKwrMe5P6Dv3FyDbh8UkfgkVs= -go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ= -go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY= +go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 h1:9n9+SOwuCyZ0L8SbQYjZ5H+GKojHN3Kl8pBLwBUQqhk= +go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0/go.mod h1:Wa9/q2K5L+ftWke2iekGNqVzwBWqyhI5OhtHKU7Qe04= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 h1:M5oKw7m89PAciR2j41n5Zq9rShK14iUadvCRy7nkSIo= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0/go.mod h1:JH6FxBlkXo/cYoU/m65W5dOQ6sqPL+jHtSJaSE7/+XQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 h1:b8xjZxHbLrXAum4SxJd1Rlm7Y/fKaB+6ACI7/e5EfSA= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0/go.mod h1:1ei0a32xOGkFoySu7y1DAHfcuIhC0pNZpvY2huXuMy4= +go.opentelemetry.io/contrib/propagators/b3 v1.19.0 h1:ulz44cpm6V5oAeg5Aw9HyqGFMS6XM7untlMEhD7YzzA= +go.opentelemetry.io/contrib/propagators/b3 v1.19.0/go.mod h1:OzCmE2IVS+asTI+odXQstRGVfXQ4bXv9nMBRK0nNyqQ= +go.opentelemetry.io/contrib/propagators/ot v1.19.0 h1:vODRLMlKN4ApM8ri0UDk8nnEeISuwxpf67sE7PmOHhE= +go.opentelemetry.io/contrib/propagators/ot v1.19.0/go.mod h1:S2Uc7th2ZmLiHu0lrCmDCgTQ/y5Nbbis+TNjR1jjm4Q= +go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= +go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 h1:IAtl+7gua134xcV3NieDhJHjjOVeJhXAnYf/0hswjUY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0/go.mod h1:w+pXobnBzh95MNIkeIuAKcHe/Uu/CX2PKIvBP6ipKRA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32ay7mJG2leczfREEhoW3VfSZIvHaB+gvVo1o8DQ8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4= +go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= +go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes= +go.opentelemetry.io/otel/exporters/zipkin v1.18.0 h1:ZqrHgvega5NIiScTiVrtpZSpEmjUdwzkhuuCEIMAp+s= +go.opentelemetry.io/otel/exporters/zipkin v1.18.0/go.mod h1:C80yIYcSceQipAZb4Ah11EE/yERlyc1MtqJG2xP7p+s= +go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= +go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= +go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= +go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= +go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= +go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= +go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= +go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -720,8 +760,8 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -780,6 +820,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -817,10 +858,10 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -832,8 +873,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -846,6 +887,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -864,6 +906,7 @@ golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -890,6 +933,7 @@ golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -911,14 +955,19 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -930,6 +979,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -997,6 +1047,7 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1070,8 +1121,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13 h1:U7+wNaVuSTaUqNvK2+osJ9ejEZxbjHHk8F2b6Hpx0AE= +google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:RdyHbowztCGQySiCvQPgWQWgWhGnouTdCflKoDBt32U= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1088,8 +1143,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= +google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1135,8 +1190,12 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0= gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8= +gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c= +gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I= gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/plugin/opentelemetry v0.1.4 h1:7p0ocWELjSSRI7NCKPW2mVe6h43YPini99sNJcbsTuc= +gorm.io/plugin/opentelemetry v0.1.4/go.mod h1:tndJHOdvPT0pyGhOb8E2209eXJCUxhC5UpKw7bGVWeI= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/internal/pkg/gorm_postgres/db.go b/internal/pkg/gorm_postgres/db.go index 0966a505..3b86314a 100644 --- a/internal/pkg/gorm_postgres/db.go +++ b/internal/pkg/gorm_postgres/db.go @@ -24,7 +24,8 @@ func NewGorm(cfg *GormOptions) (*gorm.DB, error) { } var dataSourceName string - dataSourceName = fmt.Sprintf("host=%s port=%d user=%s dbname=%s password=%s", + dataSourceName = fmt.Sprintf( + "host=%s port=%d user=%s dbname=%s password=%s", cfg.Host, cfg.Port, cfg.User, @@ -59,7 +60,10 @@ func createDB(cfg *GormOptions) error { var exists int rows, err := sqldb.Query( - fmt.Sprintf("SELECT 1 FROM pg_catalog.pg_database WHERE datname='%s'", cfg.DBName), + fmt.Sprintf( + "SELECT 1 FROM pg_catalog.pg_database WHERE datname='%s'", + cfg.DBName, + ), ) if err != nil { return err diff --git a/internal/pkg/gorm_postgres/gorm_postgres_fx.go b/internal/pkg/gorm_postgres/gorm_postgres_fx.go index b25441bb..742e68a5 100644 --- a/internal/pkg/gorm_postgres/gorm_postgres_fx.go +++ b/internal/pkg/gorm_postgres/gorm_postgres_fx.go @@ -6,6 +6,8 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health" "go.uber.org/fx" + "gorm.io/gorm" + "gorm.io/plugin/opentelemetry/tracing" ) // Module provided to fxlog @@ -22,4 +24,10 @@ var Module = fx.Module( fx.ResultTags(fmt.Sprintf(`group:"%s"`, "healths")), ), ), + fx.Invoke(EnableTracing), ) + +func EnableTracing(gormDb *gorm.DB) error { + // add tracing to gorm + return gormDb.Use(tracing.NewPlugin()) +} diff --git a/internal/pkg/logger/zap/zap_logger.go b/internal/pkg/logger/zap/zap_logger.go index bb142a9d..7040eddf 100644 --- a/internal/pkg/logger/zap/zap_logger.go +++ b/internal/pkg/logger/zap/zap_logger.go @@ -10,6 +10,7 @@ import ( config2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/models" + "github.com/uptrace/opentelemetry-go-extra/otelzap" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) @@ -40,9 +41,13 @@ var loggerLevelMap = map[string]zapcore.Level{ } // NewZapLogger create new zap logger -func NewZapLogger(cfg *config2.LogOptions, env environemnt.Environment) ZapLogger { +func NewZapLogger( + cfg *config2.LogOptions, + env environemnt.Environment, +) ZapLogger { zapLogger := &zapLogger{level: cfg.LogLevel, logOptions: cfg} zapLogger.initLogger(env) + return zapLogger } @@ -109,6 +114,9 @@ func (l *zapLogger) initLogger(env environemnt.Environment) { logger := zap.New(core, options...) + // add logs as events to tracing + logger = otelzap.New(logger).Logger + l.logger = logger l.sugarLogger = logger.Sugar() } diff --git a/internal/pkg/mongodb/mongo_fx.go b/internal/pkg/mongodb/mongo_fx.go index f4ec39a4..b3336d0b 100644 --- a/internal/pkg/mongodb/mongo_fx.go +++ b/internal/pkg/mongodb/mongo_fx.go @@ -34,7 +34,11 @@ var ( mongoInvokes = fx.Invoke(registerHooks) //nolint:gochecknoglobals ) -func registerHooks(lc fx.Lifecycle, client *mongo.Client, logger logger.Logger) { +func registerHooks( + lc fx.Lifecycle, + client *mongo.Client, + logger logger.Logger, +) { lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { err := client.Ping(ctx, nil) diff --git a/internal/pkg/mongodb/mongodb.go b/internal/pkg/mongodb/mongodb.go index e448c09f..5098b90d 100644 --- a/internal/pkg/mongodb/mongodb.go +++ b/internal/pkg/mongodb/mongodb.go @@ -8,6 +8,7 @@ import ( "github.com/kamva/mgm/v3" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" + "go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo" _ "github.com/golang-migrate/migrate/v4/source/file" ) @@ -21,15 +22,25 @@ const ( // NewMongoDB Create new MongoDB client func NewMongoDB(cfg *MongoDbOptions) (*mongo.Client, error) { - uriAddress := fmt.Sprintf("mongodb://%s:%s@%s:%d", cfg.User, cfg.Password, cfg.Host, cfg.Port) + uriAddress := fmt.Sprintf( + "mongodb://%s:%s@%s:%d", + cfg.User, + cfg.Password, + cfg.Host, + cfg.Port, + ) opt := options.Client().ApplyURI(uriAddress). SetConnectTimeout(connectTimeout). SetMaxConnIdleTime(maxConnIdleTime). SetMinPoolSize(minPoolSize). SetMaxPoolSize(maxPoolSize) + // add tracing + opt.Monitor = otelmongo.NewMonitor() if cfg.UseAuth { - opt = opt.SetAuth(options.Credential{Username: cfg.User, Password: cfg.Password}) + opt = opt.SetAuth( + options.Credential{Username: cfg.User, Password: cfg.Password}, + ) } ctx := context.Background() diff --git a/internal/pkg/otel/config/open_telemtry_options.go b/internal/pkg/otel/config/open_telemtry_options.go index c1e457f7..7a68c7a8 100644 --- a/internal/pkg/otel/config/open_telemtry_options.go +++ b/internal/pkg/otel/config/open_telemtry_options.go @@ -8,8 +8,6 @@ import ( "github.com/iancoleman/strcase" ) -var optionName = strcase.ToLowerCamel(typeMapper.GetTypeNameByT[OpenTelemetryOptions]()) - type OpenTelemetryOptions struct { Enabled bool `mapstructure:"enabled"` ServiceName string `mapstructure:"serviceName"` @@ -23,8 +21,7 @@ type OpenTelemetryOptions struct { } type JaegerExporterOptions struct { - AgentHost string `mapstructure:"agentHost"` - AgentPort string `mapstructure:"agentPort"` + OtlpEndpoint string `mapstructure:"otlpEndpoint"` } type ZipkinExporterOptions struct { @@ -38,6 +35,12 @@ type OTelMetricsOptions struct { MetricsRoutePath string `mapstructure:"metricsRoutePath"` } -func ProvideOtelConfig(environment environemnt.Environment) (*OpenTelemetryOptions, error) { +func ProvideOtelConfig( + environment environemnt.Environment, +) (*OpenTelemetryOptions, error) { + optionName := strcase.ToLowerCamel( + typeMapper.GetTypeNameByT[OpenTelemetryOptions](), + ) + return config.BindConfigKey[*OpenTelemetryOptions](optionName, environment) } diff --git a/internal/pkg/otel/tracing/tracing.go b/internal/pkg/otel/tracing/tracing.go index 3bd46d39..8dc8c569 100644 --- a/internal/pkg/otel/tracing/tracing.go +++ b/internal/pkg/otel/tracing/tracing.go @@ -1,9 +1,10 @@ package tracing import ( + "context" "fmt" - "log" "os" + "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" config2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/config" @@ -12,13 +13,15 @@ import ( "go.opentelemetry.io/contrib/propagators/ot" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/exporters/jaeger" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/exporters/zipkin" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/resource" tracesdk "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" _ "go.opentelemetry.io/otel" ) @@ -76,7 +79,9 @@ func NewOtelTracing( // Register our TracerProvider as the global so any imported // instrumentation in the future will default to using it. otel.SetTracerProvider(openTel.TracerProvider) - otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagators...)) + otel.SetTextMapPropagator( + propagation.NewCompositeTextMapPropagator(propagators...), + ) // https://trstringer.com/otel-part2-instrumentation/ // Finally, set the tracer that can be used for this package. global app tracer @@ -124,19 +129,41 @@ func (o *TracingOpenTelemetry) configTracerProvider() error { } func (o *TracingOpenTelemetry) configExporters() error { - logger := log.New(os.Stderr, "otel_log", log.Ldate|log.Ltime|log.Llongfile) - if o.config.JaegerExporterOptions != nil { - // Create the Jaeger exporter - jaegerExporter, err := jaeger.New(jaeger.WithAgentEndpoint( - jaeger.WithAgentHost(o.config.JaegerExporterOptions.AgentHost), - jaeger.WithAgentPort(o.config.JaegerExporterOptions.AgentPort), - jaeger.WithLogger(logger), - )) + // jaeger exporter removed from otel spec (it used jaeger agent and jaeger agent port), now we should use OTLP which supports by jaeger now by its built-in `collector` + // https://www.jaegertracing.io/docs/1.38/apis/#opentelemetry-protocol-stable + // https://deploy-preview-1892--opentelemetry.netlify.app/blog/2022/jaeger-native-otlp/ + // https://www.jaegertracing.io/docs/1.49/getting-started/ + // https://opentelemetry.io/docs/instrumentation/go/exporters/ + // https://opentelemetry.io/docs/specs/otlp/ + // https://github.com/open-telemetry/opentelemetry-go/pull/4467 + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + + conn, err := grpc.DialContext( + ctx, + o.config.JaegerExporterOptions.OtlpEndpoint, // default OTLP endpoint address is `localhost:4317` + // Note the use of insecure transport here. TLS is recommended in production. + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithBlock(), + ) if err != nil { - return err + return fmt.Errorf( + "failed to create gRPC connection to collector: %w", + err, + ) + } + + // Set up a trace exporter + jaegerTraceExporter, err := otlptracegrpc.New( + ctx, + otlptracegrpc.WithGRPCConn(conn), + ) + if err != nil { + return fmt.Errorf("failed to create trace exporter: %w", err) } - o.jaegerExporter = jaegerExporter + + o.jaegerExporter = jaegerTraceExporter } if o.config.ZipkinExporterOptions != nil { zipkinExporter, err := zipkin.New( @@ -149,7 +176,12 @@ func (o *TracingOpenTelemetry) configExporters() error { o.zipkinExporter = zipkinExporter } if o.config.UseStdout { - stdExporter, err := stdouttrace.New(stdouttrace.WithPrettyPrint()) + stdExporter, err := stdouttrace.New( + stdouttrace.WithWriter( + os.Stdout, + ), // stdExporter default is `stdouttrace.WithWriter(os.Stdout)`, we can remove this also + stdouttrace.WithPrettyPrint(), // make output json with pretty printing + ) if err != nil { return fmt.Errorf("creating stdout exporter: %w", err) } diff --git a/internal/services/catalog_read_service/config/config.development.json b/internal/services/catalog_read_service/config/config.development.json index df1a7ecc..3c60ef3d 100644 --- a/internal/services/catalog_read_service/config/config.development.json +++ b/internal/services/catalog_read_service/config/config.development.json @@ -55,15 +55,15 @@ "database": "catalogs_service", "useAuth": true }, - "OpenTelemetryOptions": { + "openTelemetryOptions": { "enable": true, "serviceName": "catalogs-read-service", "instrumentationName": "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice", "id": 1, "alwaysOnSampler": true, + "useStdout": false, "jaegerExporterOptions": { - "agentHost": "localhost", - "agentPort": "6831" + "otlpEndpoint": "localhost:4317" }, "zipkinExporterOptions": { "url": "http://localhost:9411/api/v2/spans" diff --git a/internal/services/catalog_read_service/config/config.test.json b/internal/services/catalog_read_service/config/config.test.json index 0cadbdb1..883d8bb9 100644 --- a/internal/services/catalog_read_service/config/config.test.json +++ b/internal/services/catalog_read_service/config/config.test.json @@ -53,15 +53,15 @@ "database": "catalogs_service", "useAuth": true }, - "OpenTelemetryOptions": { + "openTelemetryOptions": { "enable": true, "serviceName": "catalogs-read-service", "instrumentationName": "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice", "id": 1, "alwaysOnSampler": true, + "useStdout": false, "jaegerExporterOptions": { - "agentHost": "localhost", - "agentPort": "6831" + "otlpEndpoint": "localhost:4317" }, "zipkinExporterOptions": { "url": "http://localhost:9411/api/v2/spans" diff --git a/internal/services/catalog_read_service/go.mod b/internal/services/catalog_read_service/go.mod index e3343eb9..b91826fd 100644 --- a/internal/services/catalog_read_service/go.mod +++ b/internal/services/catalog_read_service/go.mod @@ -16,7 +16,7 @@ require ( github.com/mehdihadeli/go-mediatr v1.1.10 github.com/michaelklishin/rabbit-hole v1.5.0 github.com/pterm/pterm v0.12.69 - github.com/redis/go-redis/v9 v9.0.5 + github.com/redis/go-redis/v9 v9.2.0 github.com/satori/go.uuid v1.2.0 github.com/smartystreets/goconvey v1.8.1 github.com/spf13/cobra v1.7.0 @@ -24,9 +24,9 @@ require ( github.com/swaggo/echo-swagger v1.4.1 github.com/swaggo/swag v1.16.2 go.mongodb.org/mongo-driver v1.12.1 - go.opentelemetry.io/otel v1.17.0 - go.opentelemetry.io/otel/metric v1.17.0 - go.opentelemetry.io/otel/trace v1.17.0 + go.opentelemetry.io/otel v1.18.0 + go.opentelemetry.io/otel/metric v1.18.0 + go.opentelemetry.io/otel/trace v1.18.0 go.uber.org/fx v1.20.0 ) @@ -40,6 +40,7 @@ require ( github.com/KyleBanks/depth v1.2.1 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/hcsshim v0.11.0 // indirect github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 // indirect github.com/ahmetb/go-linq/v3 v3.2.0 // indirect github.com/ajg/form v1.5.1 // indirect @@ -51,12 +52,12 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/containerd/console v1.0.3 // indirect - github.com/containerd/containerd v1.7.5 // indirect + github.com/containerd/containerd v1.7.6 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker v24.0.5+incompatible // indirect + github.com/docker/docker v24.0.6+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/doug-martin/goqu/v9 v9.18.0 // indirect @@ -66,6 +67,7 @@ require ( github.com/ghodss/yaml v1.0.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.20.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/spec v0.20.9 // indirect @@ -87,6 +89,7 @@ require ( github.com/gopherjs/gopherjs v1.17.2 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/imkira/go-interpol v1.0.0 // indirect @@ -107,12 +110,13 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/jtolds/gls v4.20.0+incompatible // indirect github.com/kamva/mgm/v3 v3.5.0 // indirect - github.com/klauspost/compress v1.16.7 // indirect + github.com/klauspost/compress v1.17.0 // indirect github.com/labstack/gommon v0.4.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/lithammer/fuzzysearch v1.1.8 // indirect + github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -129,12 +133,13 @@ require ( github.com/nolleh/caption_json_formatter v0.2.2 // indirect github.com/onsi/ginkgo v1.16.5 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc4 // indirect + github.com/opencontainers/image-spec v1.1.0-rc5 // indirect github.com/opencontainers/runc v1.1.9 // indirect github.com/openzipkin/zipkin-go v0.4.2 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.44.0 // indirect @@ -145,6 +150,8 @@ require ( github.com/rivo/uniseg v0.4.4 // indirect github.com/samber/lo v1.38.1 // indirect github.com/sergi/go-diff v1.2.0 // indirect + github.com/shirou/gopsutil/v3 v3.23.8 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smarty/assertions v1.15.0 // indirect github.com/spf13/afero v1.9.5 // indirect @@ -152,14 +159,17 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.16.0 // indirect - github.com/streadway/amqp v1.1.0 // indirect github.com/stretchr/objx v0.5.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/swaggo/files/v2 v2.0.0 // indirect - github.com/testcontainers/testcontainers-go v0.23.0 // indirect + github.com/testcontainers/testcontainers-go v0.24.1 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect - github.com/uptrace/bun v1.1.14 // indirect - github.com/uptrace/bun/driver/pgdriver v1.1.14 // indirect + github.com/uptrace/bun v1.1.16 // indirect + github.com/uptrace/bun/driver/pgdriver v1.1.16 // indirect + github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 // indirect + github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.27.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect @@ -176,18 +186,22 @@ require ( github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect github.com/yudai/gojsondiff v1.0.0 // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect - go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.43.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0 // indirect - go.opentelemetry.io/contrib/propagators/ot v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.40.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.17.0 // indirect - go.opentelemetry.io/otel/exporters/zipkin v1.17.0 // indirect - go.opentelemetry.io/otel/sdk v1.17.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.40.0 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 // indirect + go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 // indirect + go.opentelemetry.io/contrib/propagators/ot v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.41.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 // indirect + go.opentelemetry.io/otel/exporters/zipkin v1.18.0 // indirect + go.opentelemetry.io/otel/sdk v1.18.0 // indirect + go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect + go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/dig v1.17.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.25.0 // indirect + go.uber.org/zap v1.26.0 // indirect golang.org/x/crypto v0.13.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/mod v0.12.0 // indirect @@ -198,14 +212,16 @@ require ( golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/grpc v1.57.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect + google.golang.org/grpc v1.58.1 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gorm.io/driver/postgres v1.5.2 // indirect gorm.io/gorm v1.25.4 // indirect + gorm.io/plugin/opentelemetry v0.1.4 // indirect mellium.im/sasl v0.3.1 // indirect moul.io/http2curl v1.0.1-0.20190925090545-5cd742060b0e // indirect ) diff --git a/internal/services/catalog_read_service/go.sum b/internal/services/catalog_read_service/go.sum index 861a54b6..97b57c7b 100644 --- a/internal/services/catalog_read_service/go.sum +++ b/internal/services/catalog_read_service/go.sum @@ -33,8 +33,8 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= -cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= +cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -83,8 +83,8 @@ github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA4 github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek= -github.com/Microsoft/hcsshim v0.10.0-rc.8/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= +github.com/Microsoft/hcsshim v0.11.0 h1:7EFNIY4igHEXUdj1zXgAyU3fLc7QfOKHbkldRVTBdiM= +github.com/Microsoft/hcsshim v0.11.0/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4= @@ -108,10 +108,12 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/brianvoe/gofakeit/v6 v6.23.2 h1:lVde18uhad5wII/f5RMVFLtdQNE0HaGFuBUXmYKk8i8= github.com/brianvoe/gofakeit/v6 v6.23.2/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8= -github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao= github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= -github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/caarlos0/env/v8 v8.0.0 h1:POhxHhSpuxrLMIdvTGARuZqR4Jjm8AYmoi/JKlcScs0= github.com/caarlos0/env/v8 v8.0.0/go.mod h1:7K4wMY9bH0esiXSSHlfHLX5xKGQMnkH5Fk4TDSSSzfo= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= @@ -136,8 +138,8 @@ github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMe github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.7.5 h1:i9T9XpAWMe11BHMN7pu1BZqOGjXaKTPyz2v+KYOZgkY= -github.com/containerd/containerd v1.7.5/go.mod h1:ieJNCSzASw2shSGYLHx8NAE7WsZ/gEigo5fQ78W5Zvw= +github.com/containerd/containerd v1.7.6 h1:oNAVsnhPoy4BTPQivLgTzI9Oleml9l/+eYIDYXRCYo8= +github.com/containerd/containerd v1.7.6/go.mod h1:SY6lrkkuJT40BVNO37tlYTSnKJnP5AXBc0fhx0q+TJ4= github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= @@ -160,12 +162,12 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/docker/cli v24.0.5+incompatible h1:WeBimjvS0eKdH4Ygx+ihVq1Q++xg36M/rMi4aXAvodc= -github.com/docker/cli v24.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY= +github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY= -github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE= +github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= @@ -180,8 +182,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= -github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/fasthttp/websocket v1.4.3-rc.6 h1:omHqsl8j+KXpmzRjF8bmzOSYJ8GnS0E3efi1wYT+niY= github.com/fasthttp/websocket v1.4.3-rc.6/go.mod h1:43W9OM2T8FeXpCWMsBd9Cb7nE2CACNqNvCqQCoty/Lc= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= @@ -209,6 +211,9 @@ github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= @@ -252,6 +257,8 @@ github.com/golang-migrate/migrate/v4 v4.16.2 h1:8coYbMKUyInrFk1lfGfRovTLAW7PhWp8 github.com/golang-migrate/migrate/v4 v4.16.2/go.mod h1:pfcJX4nPHaVdc5nmdCikFBWtm+UBpiZjRNNsyBbp0/o= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -297,6 +304,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= @@ -337,6 +345,8 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= @@ -430,8 +440,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= @@ -470,6 +480,9 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a h1:N9zuLhTvBSRt0gWSiJswwQ2HqDmtX/ZCDJURnKUt1Ik= +github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -495,6 +508,8 @@ github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mcuadros/go-defaults v1.2.0 h1:FODb8WSf0uGaY8elWJAkoLL0Ri6AlZ1bFlenk56oZtc= @@ -539,8 +554,8 @@ github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= -github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= +github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc95/go.mod h1:z+bZxa/+Tz/FmYVWkhUajJdzFeOqjc5vrqskhVyHGUM= github.com/opencontainers/runc v1.1.9 h1:XR0VIHTGce5eWPkaPesqTBrhW2yAcaraWfsEalNwQLM= @@ -562,6 +577,9 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -586,8 +604,9 @@ github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fO github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJuQe5bzQ02jGd5Qcbgb97Flm7U= github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc= github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ= -github.com/redis/go-redis/v9 v9.0.5 h1:CuQcn5HIEeK7BgElubPP8CGtE0KakrnbBSTLjathl5o= github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= +github.com/redis/go-redis/v9 v9.2.0 h1:zwMdX0A4eVzse46YN18QhuDiM4uf3JmkOB4VZrdt5uI= +github.com/redis/go-redis/v9 v9.2.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -609,6 +628,12 @@ github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvW github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= +github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= @@ -669,15 +694,23 @@ github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0J github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04= github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/testcontainers/testcontainers-go v0.23.0 h1:ERYTSikX01QczBLPZpqsETTBO7lInqEP349phDOVJVs= -github.com/testcontainers/testcontainers-go v0.23.0/go.mod h1:3gzuZfb7T9qfcH2pHpV4RLlWrPjeWNQah6XlYQ32c4I= +github.com/testcontainers/testcontainers-go v0.24.1 h1:gJdZuQIVWnMJTo+CmQMEP7/CAagNk/0jbcUPn3OWvD8= +github.com/testcontainers/testcontainers-go v0.24.1/go.mod h1:MGBiAkCm86yXQoCiipmQCqZLVdk1uFqtMqaU1Or0MRk= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= -github.com/uptrace/bun v1.1.14 h1:S5vvNnjEynJ0CvnrBOD7MIRW7q/WbtvFXrdfy0lddAM= -github.com/uptrace/bun v1.1.14/go.mod h1:RHk6DrIisO62dv10pUOJCz5MphXThuOTpVNYEYv7NI8= -github.com/uptrace/bun/driver/pgdriver v1.1.14 h1:V2Etm7mLGS3mhx8ddxZcUnwZLX02Jmq9JTlo0sNVDhA= -github.com/uptrace/bun/driver/pgdriver v1.1.14/go.mod h1:D4FjWV9arDYct6sjMJhFoyU71SpllZRHXFRRP2Kd0Kw= +github.com/uptrace/bun v1.1.16 h1:cn9cgEMFwcyYRsQLfxCRMUxyK1WaHwOVrR3TvzEFZ/A= +github.com/uptrace/bun v1.1.16/go.mod h1:7HnsMRRvpLFUcquJxp22JO8PsWKpFQO/gNXqqsuGWg8= +github.com/uptrace/bun/driver/pgdriver v1.1.16 h1:b/NiSXk6Ldw7KLfMLbOqIkm4odHd7QiNOCPLqPFJjK4= +github.com/uptrace/bun/driver/pgdriver v1.1.16/go.mod h1:Rmfbc+7lx1z/umjMyAxkOHK81LgnGj71XC5YpA6k1vU= +github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 h1:CNznWHkrbA6o1q2H/BsH4tIHf4zbKNtndeoV+AH8z0U= +github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2/go.mod h1:7YSrHCmYPHIXjTWnKSU7EGT0TFEcm3WwSeQquwCGg38= +github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 h1:uyrW06oJi4iWvhjPLVfk4qrSP2Zm0AMozKKDmp6i4pE= +github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2/go.mod h1:PMAs2dNxP55lgt6xu0if+Jasm6s+Xpmqn6ev1NyDfnI= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -730,6 +763,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY= go.mongodb.org/mongo-driver v1.12.1 h1:nLkghSU8fQNaK7oUmDhQFsnrtcoNy7Z6LVFKsEecqgE= @@ -740,32 +775,38 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.43.0 h1:pcWR7mkuO5XMK3f0KeGpr70OTR9/ikPk0D1hHEd5dp4= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.43.0/go.mod h1:azTPpa9PvRDSNU/lQbe2CRDQoTcau5moOjS4EzhpyAY= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0 h1:7XZai4VhA473clBrOqqHdjHBImGfyEtv0qW4nnn/kAo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0/go.mod h1:1WpsUwjQrUJSNugfMlPn0rPRJ9Do7wwBgTBPK7MLiS4= -go.opentelemetry.io/contrib/propagators/b3 v1.18.0 h1:hhSlPVi9AQwOmbMmptPNLfRZOLgENdRM2kb7z9LFe1A= -go.opentelemetry.io/contrib/propagators/b3 v1.18.0/go.mod h1:qtt+pEu23D7UVP+j33G4i7LopmVu8/6/IwGu3hEm100= -go.opentelemetry.io/contrib/propagators/ot v1.18.0 h1:VmzxO7BjUU6oo0ChcKuGdKaSR0vchPxwahHZl64zVUM= -go.opentelemetry.io/contrib/propagators/ot v1.18.0/go.mod h1:5VwcOJ7OjS0uPxaxuwKHwJtkt+EAC+cgjXleXMe51z4= -go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM= -go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0= -go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4= -go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI= -go.opentelemetry.io/otel/exporters/prometheus v0.40.0 h1:9h6lCssr1j5aYVvWT6oc+ERB6R034zmsHjBRLyxrAR8= -go.opentelemetry.io/otel/exporters/prometheus v0.40.0/go.mod h1:5USWZ0ovyQB5CIM3IO3bGRSoDPMXiT3t+15gu8Zo9HQ= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.17.0 h1:Ut6hgtYcASHwCzRHkXEtSsM251cXJPW+Z9DyLwEn6iI= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.17.0/go.mod h1:TYeE+8d5CjrgBa0ZuRaDeMpIC1xZ7atg4g+nInjuSjc= -go.opentelemetry.io/otel/exporters/zipkin v1.17.0 h1:oi5+xMN3pflqWSd4EX6FiO+Cn3KbFBBzeQmD5LMIf0c= -go.opentelemetry.io/otel/exporters/zipkin v1.17.0/go.mod h1:pNir+S6/f0HFGfbXhobXLTFu60KtAzw8aGSUpt9A6VU= -go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc= -go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o= -go.opentelemetry.io/otel/sdk v1.17.0 h1:FLN2X66Ke/k5Sg3V623Q7h7nt3cHXaW1FOvKKrW0IpE= -go.opentelemetry.io/otel/sdk v1.17.0/go.mod h1:U87sE0f5vQB7hwUoW98pW5Rz4ZDuCFBZFNUBlSgmDFQ= -go.opentelemetry.io/otel/sdk/metric v0.40.0 h1:qOM29YaGcxipWjL5FzpyZDpCYrDREvX0mVlmXdOjCHU= -go.opentelemetry.io/otel/sdk/metric v0.40.0/go.mod h1:dWxHtdzdJvg+ciJUKLTKwrMe5P6Dv3FyDbh8UkfgkVs= -go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ= -go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY= +go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 h1:9n9+SOwuCyZ0L8SbQYjZ5H+GKojHN3Kl8pBLwBUQqhk= +go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0/go.mod h1:Wa9/q2K5L+ftWke2iekGNqVzwBWqyhI5OhtHKU7Qe04= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 h1:M5oKw7m89PAciR2j41n5Zq9rShK14iUadvCRy7nkSIo= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0/go.mod h1:JH6FxBlkXo/cYoU/m65W5dOQ6sqPL+jHtSJaSE7/+XQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 h1:b8xjZxHbLrXAum4SxJd1Rlm7Y/fKaB+6ACI7/e5EfSA= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0/go.mod h1:1ei0a32xOGkFoySu7y1DAHfcuIhC0pNZpvY2huXuMy4= +go.opentelemetry.io/contrib/propagators/b3 v1.19.0 h1:ulz44cpm6V5oAeg5Aw9HyqGFMS6XM7untlMEhD7YzzA= +go.opentelemetry.io/contrib/propagators/b3 v1.19.0/go.mod h1:OzCmE2IVS+asTI+odXQstRGVfXQ4bXv9nMBRK0nNyqQ= +go.opentelemetry.io/contrib/propagators/ot v1.19.0 h1:vODRLMlKN4ApM8ri0UDk8nnEeISuwxpf67sE7PmOHhE= +go.opentelemetry.io/contrib/propagators/ot v1.19.0/go.mod h1:S2Uc7th2ZmLiHu0lrCmDCgTQ/y5Nbbis+TNjR1jjm4Q= +go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= +go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 h1:IAtl+7gua134xcV3NieDhJHjjOVeJhXAnYf/0hswjUY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0/go.mod h1:w+pXobnBzh95MNIkeIuAKcHe/Uu/CX2PKIvBP6ipKRA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32ay7mJG2leczfREEhoW3VfSZIvHaB+gvVo1o8DQ8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4= +go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= +go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes= +go.opentelemetry.io/otel/exporters/zipkin v1.18.0 h1:ZqrHgvega5NIiScTiVrtpZSpEmjUdwzkhuuCEIMAp+s= +go.opentelemetry.io/otel/exporters/zipkin v1.18.0/go.mod h1:C80yIYcSceQipAZb4Ah11EE/yERlyc1MtqJG2xP7p+s= +go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= +go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= +go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= +go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= +go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= +go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= +go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= +go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -791,8 +832,8 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -906,8 +947,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -940,6 +981,7 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -967,6 +1009,7 @@ golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -991,8 +1034,11 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -1156,8 +1202,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13 h1:U7+wNaVuSTaUqNvK2+osJ9ejEZxbjHHk8F2b6Hpx0AE= +google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:RdyHbowztCGQySiCvQPgWQWgWhGnouTdCflKoDBt32U= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1174,8 +1224,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= +google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1223,8 +1273,12 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0= gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8= +gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c= +gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I= gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/plugin/opentelemetry v0.1.4 h1:7p0ocWELjSSRI7NCKPW2mVe6h43YPini99sNJcbsTuc= +gorm.io/plugin/opentelemetry v0.1.4/go.mod h1:tndJHOdvPT0pyGhOb8E2209eXJCUxhC5UpKw7bGVWeI= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/internal/services/catalog_write_service/config/config.development.json b/internal/services/catalog_write_service/config/config.development.json index 1a49c752..83a9dcef 100644 --- a/internal/services/catalog_write_service/config/config.development.json +++ b/internal/services/catalog_write_service/config/config.development.json @@ -53,10 +53,10 @@ "serviceName": "catalogs-write-service", "instrumentationName": "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice", "id": 1, + "useStdout": false, "alwaysOnSampler": true, "jaegerExporterOptions": { - "agentHost": "localhost", - "agentPort": "6831" + "otlpEndpoint": "localhost:4317" }, "zipkinExporterOptions": { "url": "http://localhost:9411/api/v2/spans" diff --git a/internal/services/catalog_write_service/config/config.test.json b/internal/services/catalog_write_service/config/config.test.json index 58a80583..73fdeed1 100644 --- a/internal/services/catalog_write_service/config/config.test.json +++ b/internal/services/catalog_write_service/config/config.test.json @@ -53,10 +53,10 @@ "serviceName": "catalogs-write-service", "instrumentationName": "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice", "id": 1, + "useStdout": true, "alwaysOnSampler": true, "jaegerExporterOptions": { - "agentHost": "localhost", - "agentPort": "6831" + "otlpEndpoint": "localhost:4317" }, "zipkinExporterOptions": { "url": "http://localhost:9411/api/v2/spans" diff --git a/internal/services/catalog_write_service/go.mod b/internal/services/catalog_write_service/go.mod index 4be37c64..85fd3478 100644 --- a/internal/services/catalog_write_service/go.mod +++ b/internal/services/catalog_write_service/go.mod @@ -26,11 +26,11 @@ require ( github.com/stretchr/testify v1.8.4 github.com/swaggo/echo-swagger v1.4.1 github.com/swaggo/swag v1.16.2 - go.opentelemetry.io/otel v1.17.0 - go.opentelemetry.io/otel/metric v1.17.0 - go.opentelemetry.io/otel/trace v1.17.0 + go.opentelemetry.io/otel v1.18.0 + go.opentelemetry.io/otel/metric v1.18.0 + go.opentelemetry.io/otel/trace v1.18.0 go.uber.org/fx v1.20.0 - google.golang.org/grpc v1.57.0 + google.golang.org/grpc v1.58.1 gopkg.in/khaiql/dbcleaner.v2 v2.3.0 gorm.io/gorm v1.25.4 ) @@ -42,11 +42,12 @@ require ( dario.cat/mergo v1.0.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/ClickHouse/ch-go v0.58.2 // indirect - github.com/ClickHouse/clickhouse-go/v2 v2.13.4 // indirect + github.com/ClickHouse/clickhouse-go/v2 v2.14.1 // indirect github.com/EventStore/EventStore-Client-Go v1.0.2 // indirect github.com/KyleBanks/depth v1.2.1 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/hcsshim v0.11.0 // indirect github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 // indirect github.com/ahmetb/go-linq/v3 v3.2.0 // indirect github.com/ajg/form v1.5.1 // indirect @@ -57,12 +58,12 @@ require ( github.com/caarlos0/env/v8 v8.0.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/containerd/console v1.0.3 // indirect - github.com/containerd/containerd v1.7.5 // indirect + github.com/containerd/containerd v1.7.6 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker v24.0.5+incompatible // indirect + github.com/docker/docker v24.0.6+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/doug-martin/goqu/v9 v9.18.0 // indirect @@ -73,6 +74,7 @@ require ( github.com/go-faster/errors v0.6.1 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.20.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/spec v0.20.9 // indirect @@ -92,6 +94,7 @@ require ( github.com/google/uuid v1.3.1 // indirect github.com/gookit/color v1.5.4 // indirect github.com/gorilla/websocket v1.4.2 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect github.com/imkira/go-interpol v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect @@ -110,12 +113,13 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/kamva/mgm/v3 v3.5.0 // indirect github.com/khaiql/dbcleaner v2.3.0+incompatible // indirect - github.com/klauspost/compress v1.16.7 // indirect + github.com/klauspost/compress v1.17.0 // indirect github.com/labstack/gommon v0.4.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/lithammer/fuzzysearch v1.1.8 // indirect + github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect @@ -130,7 +134,7 @@ require ( github.com/nolleh/caption_json_formatter v0.2.2 // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc4 // indirect + github.com/opencontainers/image-spec v1.1.0-rc5 // indirect github.com/opencontainers/runc v1.1.9 // indirect github.com/openzipkin/zipkin-go v0.4.2 // indirect github.com/paulmach/orb v0.10.0 // indirect @@ -138,26 +142,32 @@ require ( github.com/pierrec/lz4/v4 v4.1.18 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect github.com/pressly/goose/v3 v3.15.0 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/rabbitmq/amqp091-go v1.8.1 // indirect github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 // indirect - github.com/redis/go-redis/v9 v9.0.5 // indirect + github.com/redis/go-redis/v9 v9.2.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/samber/lo v1.38.1 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/sergi/go-diff v1.2.0 // indirect + github.com/shirou/gopsutil/v3 v3.23.8 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/viper v1.16.0 // indirect - github.com/streadway/amqp v1.1.0 // indirect github.com/stretchr/objx v0.5.1 // indirect github.com/swaggo/files/v2 v2.0.0 // indirect - github.com/testcontainers/testcontainers-go v0.23.0 // indirect + github.com/testcontainers/testcontainers-go v0.24.1 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect - github.com/uptrace/bun v1.1.14 // indirect - github.com/uptrace/bun/driver/pgdriver v1.1.14 // indirect + github.com/uptrace/bun v1.1.16 // indirect + github.com/uptrace/bun/driver/pgdriver v1.1.16 // indirect + github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 // indirect + github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.27.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect @@ -174,19 +184,23 @@ require ( github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect github.com/yudai/gojsondiff v1.0.0 // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect go.mongodb.org/mongo-driver v1.12.1 // indirect - go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.43.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0 // indirect - go.opentelemetry.io/contrib/propagators/ot v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.40.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.17.0 // indirect - go.opentelemetry.io/otel/exporters/zipkin v1.17.0 // indirect - go.opentelemetry.io/otel/sdk v1.17.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.40.0 // indirect + go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 // indirect + go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 // indirect + go.opentelemetry.io/contrib/propagators/ot v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.41.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 // indirect + go.opentelemetry.io/otel/exporters/zipkin v1.18.0 // indirect + go.opentelemetry.io/otel/sdk v1.18.0 // indirect + go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect + go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/dig v1.17.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.25.0 // indirect + go.uber.org/zap v1.26.0 // indirect golang.org/x/crypto v0.13.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/mod v0.12.0 // indirect @@ -196,9 +210,11 @@ require ( golang.org/x/term v0.12.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gorm.io/driver/postgres v1.5.2 // indirect + gorm.io/plugin/opentelemetry v0.1.4 // indirect mellium.im/sasl v0.3.1 // indirect moul.io/http2curl v1.0.1-0.20190925090545-5cd742060b0e // indirect ) diff --git a/internal/services/catalog_write_service/go.sum b/internal/services/catalog_write_service/go.sum index b75314c5..260213e1 100644 --- a/internal/services/catalog_write_service/go.sum +++ b/internal/services/catalog_write_service/go.sum @@ -33,8 +33,8 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= -cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= +cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -63,8 +63,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ClickHouse/ch-go v0.58.2 h1:jSm2szHbT9MCAB1rJ3WuCJqmGLi5UTjlNu+f530UTS0= github.com/ClickHouse/ch-go v0.58.2/go.mod h1:Ap/0bEmiLa14gYjCiRkYGbXvbe8vwdrfTYWhsuQ99aw= -github.com/ClickHouse/clickhouse-go/v2 v2.13.4 h1:NcvYN9ONZn3vlPMfQVUBSG5LKz+1y2wk4vaaz5QZXIg= -github.com/ClickHouse/clickhouse-go/v2 v2.13.4/go.mod h1:u1AUh8E0XqN1sU1EDzbiGLTI4KWOd+lOHimNSsdyJec= +github.com/ClickHouse/clickhouse-go/v2 v2.14.1 h1:5C2hhmZEGUVdy8CPpY3iPpfBv2kRbx5iOcflU49Rzws= +github.com/ClickHouse/clickhouse-go/v2 v2.14.1/go.mod h1:PHqbMvJTQ0EI4a1vJhmbmL/Ajr+Cin2O+WJjnYctJvg= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/EventStore/EventStore-Client-Go v1.0.2 h1:onM2TIInLhWUJwUQ/5a/8blNrrbhwrtm7Tpmg13ohiw= @@ -87,8 +87,8 @@ github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA4 github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek= -github.com/Microsoft/hcsshim v0.10.0-rc.8/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= +github.com/Microsoft/hcsshim v0.11.0 h1:7EFNIY4igHEXUdj1zXgAyU3fLc7QfOKHbkldRVTBdiM= +github.com/Microsoft/hcsshim v0.11.0/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4= @@ -114,10 +114,12 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/brianvoe/gofakeit/v6 v6.23.2 h1:lVde18uhad5wII/f5RMVFLtdQNE0HaGFuBUXmYKk8i8= github.com/brianvoe/gofakeit/v6 v6.23.2/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8= -github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao= github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= -github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/caarlos0/env/v8 v8.0.0 h1:POhxHhSpuxrLMIdvTGARuZqR4Jjm8AYmoi/JKlcScs0= github.com/caarlos0/env/v8 v8.0.0/go.mod h1:7K4wMY9bH0esiXSSHlfHLX5xKGQMnkH5Fk4TDSSSzfo= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= @@ -142,8 +144,8 @@ github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMe github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.7.5 h1:i9T9XpAWMe11BHMN7pu1BZqOGjXaKTPyz2v+KYOZgkY= -github.com/containerd/containerd v1.7.5/go.mod h1:ieJNCSzASw2shSGYLHx8NAE7WsZ/gEigo5fQ78W5Zvw= +github.com/containerd/containerd v1.7.6 h1:oNAVsnhPoy4BTPQivLgTzI9Oleml9l/+eYIDYXRCYo8= +github.com/containerd/containerd v1.7.6/go.mod h1:SY6lrkkuJT40BVNO37tlYTSnKJnP5AXBc0fhx0q+TJ4= github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= @@ -168,12 +170,12 @@ github.com/denisenkom/go-mssqldb v0.12.3 h1:pBSGx9Tq67pBOTLmxNuirNTeB8Vjmf886Kx+ github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDrorD1Vrm1KEz5hxDo= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/docker/cli v24.0.5+incompatible h1:WeBimjvS0eKdH4Ygx+ihVq1Q++xg36M/rMi4aXAvodc= -github.com/docker/cli v24.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY= +github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY= -github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE= +github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= @@ -190,8 +192,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= -github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/fasthttp/websocket v1.4.3-rc.6 h1:omHqsl8j+KXpmzRjF8bmzOSYJ8GnS0E3efi1wYT+niY= github.com/fasthttp/websocket v1.4.3-rc.6/go.mod h1:43W9OM2T8FeXpCWMsBd9Cb7nE2CACNqNvCqQCoty/Lc= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= @@ -223,6 +225,9 @@ github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= @@ -276,6 +281,8 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2V github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -321,6 +328,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= @@ -361,6 +369,8 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= @@ -456,8 +466,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= @@ -496,6 +506,9 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a h1:N9zuLhTvBSRt0gWSiJswwQ2HqDmtX/ZCDJURnKUt1Ik= +github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -569,8 +582,8 @@ github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= -github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= +github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc95/go.mod h1:z+bZxa/+Tz/FmYVWkhUajJdzFeOqjc5vrqskhVyHGUM= github.com/opencontainers/runc v1.1.9 h1:XR0VIHTGce5eWPkaPesqTBrhW2yAcaraWfsEalNwQLM= @@ -597,6 +610,9 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/pressly/goose/v3 v3.15.0 h1:6tY5aDqFknY6VZkorFGgZtWygodZQxfmmEF4rqyJW9k= github.com/pressly/goose/v3 v3.15.0/go.mod h1:LlIo3zGccjb/YUgG+Svdb9Er14vefRdlDI7URCDrwYo= github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= @@ -623,8 +639,9 @@ github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fO github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJuQe5bzQ02jGd5Qcbgb97Flm7U= github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc= github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ= -github.com/redis/go-redis/v9 v9.0.5 h1:CuQcn5HIEeK7BgElubPP8CGtE0KakrnbBSTLjathl5o= github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= +github.com/redis/go-redis/v9 v9.2.0 h1:zwMdX0A4eVzse46YN18QhuDiM4uf3JmkOB4VZrdt5uI= +github.com/redis/go-redis/v9 v9.2.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -650,6 +667,12 @@ github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= +github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= @@ -706,17 +729,25 @@ github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0J github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04= github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/testcontainers/testcontainers-go v0.23.0 h1:ERYTSikX01QczBLPZpqsETTBO7lInqEP349phDOVJVs= -github.com/testcontainers/testcontainers-go v0.23.0/go.mod h1:3gzuZfb7T9qfcH2pHpV4RLlWrPjeWNQah6XlYQ32c4I= -github.com/testcontainers/testcontainers-go/modules/postgres v0.23.0 h1:OEGUC1YTN1RyS4xqsHmlyYkBWm9lMJcswoV4JSHJQOM= -github.com/testcontainers/testcontainers-go/modules/postgres v0.23.0/go.mod h1:YnqIhPwhjqVbJBuvSRJS6pa9Cy1PDRJcrM6T63Uw2ms= +github.com/testcontainers/testcontainers-go v0.24.1 h1:gJdZuQIVWnMJTo+CmQMEP7/CAagNk/0jbcUPn3OWvD8= +github.com/testcontainers/testcontainers-go v0.24.1/go.mod h1:MGBiAkCm86yXQoCiipmQCqZLVdk1uFqtMqaU1Or0MRk= +github.com/testcontainers/testcontainers-go/modules/postgres v0.24.1 h1:lSJLORAjkj8PoiZef+KoziJbhpRmL1ELzJXQQ8L3s1U= +github.com/testcontainers/testcontainers-go/modules/postgres v0.24.1/go.mod h1:QG4rCYFma/K7CbAFtrqCIn87EI6bNRWaW+Ebt4UV2WA= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= -github.com/uptrace/bun v1.1.14 h1:S5vvNnjEynJ0CvnrBOD7MIRW7q/WbtvFXrdfy0lddAM= -github.com/uptrace/bun v1.1.14/go.mod h1:RHk6DrIisO62dv10pUOJCz5MphXThuOTpVNYEYv7NI8= -github.com/uptrace/bun/driver/pgdriver v1.1.14 h1:V2Etm7mLGS3mhx8ddxZcUnwZLX02Jmq9JTlo0sNVDhA= -github.com/uptrace/bun/driver/pgdriver v1.1.14/go.mod h1:D4FjWV9arDYct6sjMJhFoyU71SpllZRHXFRRP2Kd0Kw= +github.com/uptrace/bun v1.1.16 h1:cn9cgEMFwcyYRsQLfxCRMUxyK1WaHwOVrR3TvzEFZ/A= +github.com/uptrace/bun v1.1.16/go.mod h1:7HnsMRRvpLFUcquJxp22JO8PsWKpFQO/gNXqqsuGWg8= +github.com/uptrace/bun/driver/pgdriver v1.1.16 h1:b/NiSXk6Ldw7KLfMLbOqIkm4odHd7QiNOCPLqPFJjK4= +github.com/uptrace/bun/driver/pgdriver v1.1.16/go.mod h1:Rmfbc+7lx1z/umjMyAxkOHK81LgnGj71XC5YpA6k1vU= +github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 h1:CNznWHkrbA6o1q2H/BsH4tIHf4zbKNtndeoV+AH8z0U= +github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2/go.mod h1:7YSrHCmYPHIXjTWnKSU7EGT0TFEcm3WwSeQquwCGg38= +github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 h1:uyrW06oJi4iWvhjPLVfk4qrSP2Zm0AMozKKDmp6i4pE= +github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2/go.mod h1:PMAs2dNxP55lgt6xu0if+Jasm6s+Xpmqn6ev1NyDfnI= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -771,6 +802,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY= go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= @@ -782,32 +815,38 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.43.0 h1:pcWR7mkuO5XMK3f0KeGpr70OTR9/ikPk0D1hHEd5dp4= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.43.0/go.mod h1:azTPpa9PvRDSNU/lQbe2CRDQoTcau5moOjS4EzhpyAY= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0 h1:7XZai4VhA473clBrOqqHdjHBImGfyEtv0qW4nnn/kAo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0/go.mod h1:1WpsUwjQrUJSNugfMlPn0rPRJ9Do7wwBgTBPK7MLiS4= -go.opentelemetry.io/contrib/propagators/b3 v1.18.0 h1:hhSlPVi9AQwOmbMmptPNLfRZOLgENdRM2kb7z9LFe1A= -go.opentelemetry.io/contrib/propagators/b3 v1.18.0/go.mod h1:qtt+pEu23D7UVP+j33G4i7LopmVu8/6/IwGu3hEm100= -go.opentelemetry.io/contrib/propagators/ot v1.18.0 h1:VmzxO7BjUU6oo0ChcKuGdKaSR0vchPxwahHZl64zVUM= -go.opentelemetry.io/contrib/propagators/ot v1.18.0/go.mod h1:5VwcOJ7OjS0uPxaxuwKHwJtkt+EAC+cgjXleXMe51z4= -go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM= -go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0= -go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4= -go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI= -go.opentelemetry.io/otel/exporters/prometheus v0.40.0 h1:9h6lCssr1j5aYVvWT6oc+ERB6R034zmsHjBRLyxrAR8= -go.opentelemetry.io/otel/exporters/prometheus v0.40.0/go.mod h1:5USWZ0ovyQB5CIM3IO3bGRSoDPMXiT3t+15gu8Zo9HQ= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.17.0 h1:Ut6hgtYcASHwCzRHkXEtSsM251cXJPW+Z9DyLwEn6iI= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.17.0/go.mod h1:TYeE+8d5CjrgBa0ZuRaDeMpIC1xZ7atg4g+nInjuSjc= -go.opentelemetry.io/otel/exporters/zipkin v1.17.0 h1:oi5+xMN3pflqWSd4EX6FiO+Cn3KbFBBzeQmD5LMIf0c= -go.opentelemetry.io/otel/exporters/zipkin v1.17.0/go.mod h1:pNir+S6/f0HFGfbXhobXLTFu60KtAzw8aGSUpt9A6VU= -go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc= -go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o= -go.opentelemetry.io/otel/sdk v1.17.0 h1:FLN2X66Ke/k5Sg3V623Q7h7nt3cHXaW1FOvKKrW0IpE= -go.opentelemetry.io/otel/sdk v1.17.0/go.mod h1:U87sE0f5vQB7hwUoW98pW5Rz4ZDuCFBZFNUBlSgmDFQ= -go.opentelemetry.io/otel/sdk/metric v0.40.0 h1:qOM29YaGcxipWjL5FzpyZDpCYrDREvX0mVlmXdOjCHU= -go.opentelemetry.io/otel/sdk/metric v0.40.0/go.mod h1:dWxHtdzdJvg+ciJUKLTKwrMe5P6Dv3FyDbh8UkfgkVs= -go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ= -go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY= +go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 h1:9n9+SOwuCyZ0L8SbQYjZ5H+GKojHN3Kl8pBLwBUQqhk= +go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0/go.mod h1:Wa9/q2K5L+ftWke2iekGNqVzwBWqyhI5OhtHKU7Qe04= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 h1:M5oKw7m89PAciR2j41n5Zq9rShK14iUadvCRy7nkSIo= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0/go.mod h1:JH6FxBlkXo/cYoU/m65W5dOQ6sqPL+jHtSJaSE7/+XQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 h1:b8xjZxHbLrXAum4SxJd1Rlm7Y/fKaB+6ACI7/e5EfSA= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0/go.mod h1:1ei0a32xOGkFoySu7y1DAHfcuIhC0pNZpvY2huXuMy4= +go.opentelemetry.io/contrib/propagators/b3 v1.19.0 h1:ulz44cpm6V5oAeg5Aw9HyqGFMS6XM7untlMEhD7YzzA= +go.opentelemetry.io/contrib/propagators/b3 v1.19.0/go.mod h1:OzCmE2IVS+asTI+odXQstRGVfXQ4bXv9nMBRK0nNyqQ= +go.opentelemetry.io/contrib/propagators/ot v1.19.0 h1:vODRLMlKN4ApM8ri0UDk8nnEeISuwxpf67sE7PmOHhE= +go.opentelemetry.io/contrib/propagators/ot v1.19.0/go.mod h1:S2Uc7th2ZmLiHu0lrCmDCgTQ/y5Nbbis+TNjR1jjm4Q= +go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= +go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 h1:IAtl+7gua134xcV3NieDhJHjjOVeJhXAnYf/0hswjUY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0/go.mod h1:w+pXobnBzh95MNIkeIuAKcHe/Uu/CX2PKIvBP6ipKRA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32ay7mJG2leczfREEhoW3VfSZIvHaB+gvVo1o8DQ8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4= +go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= +go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes= +go.opentelemetry.io/otel/exporters/zipkin v1.18.0 h1:ZqrHgvega5NIiScTiVrtpZSpEmjUdwzkhuuCEIMAp+s= +go.opentelemetry.io/otel/exporters/zipkin v1.18.0/go.mod h1:C80yIYcSceQipAZb4Ah11EE/yERlyc1MtqJG2xP7p+s= +go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= +go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= +go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= +go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= +go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= +go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= +go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= +go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -833,8 +872,8 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -948,8 +987,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -982,6 +1021,7 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1009,6 +1049,7 @@ golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1033,8 +1074,11 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -1198,8 +1242,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13 h1:U7+wNaVuSTaUqNvK2+osJ9ejEZxbjHHk8F2b6Hpx0AE= +google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:RdyHbowztCGQySiCvQPgWQWgWhGnouTdCflKoDBt32U= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1216,8 +1264,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= +google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1267,8 +1315,12 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0= gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8= +gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c= +gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I= gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/plugin/opentelemetry v0.1.4 h1:7p0ocWELjSSRI7NCKPW2mVe6h43YPini99sNJcbsTuc= +gorm.io/plugin/opentelemetry v0.1.4/go.mod h1:tndJHOdvPT0pyGhOb8E2209eXJCUxhC5UpKw7bGVWeI= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/internal/services/catalog_write_service/internal/shared/app/app.go b/internal/services/catalog_write_service/internal/shared/app/app.go index c0a91e37..77492e8c 100644 --- a/internal/services/catalog_write_service/internal/shared/app/app.go +++ b/internal/services/catalog_write_service/internal/shared/app/app.go @@ -1,6 +1,9 @@ package app import ( + "context" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/configurations/catalogs" ) @@ -23,5 +26,10 @@ func (a *App) Run() { app.MapCatalogsEndpoints() app.Logger().Info("Starting catalog_service application") + app.ResolveFunc(func(tracer tracing.AppTracer) { + _, span := tracer.Start(context.Background(), "Application started") + span.End() + }) + app.Run() } diff --git a/internal/services/order_service/config/config.development.json b/internal/services/order_service/config/config.development.json index 51199dc2..5dca0a45 100644 --- a/internal/services/order_service/config/config.development.json +++ b/internal/services/order_service/config/config.development.json @@ -48,15 +48,15 @@ "httpPort": 15672 } }, - "OpenTelemetryOptions": { + "openTelemetryOptions": { "enable": true, "serviceName": "orders-service", "instrumentationName": "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice", "id": 3, "alwaysOnSampler": true, + "useStdout": false, "jaegerExporterOptions": { - "agentHost": "localhost", - "agentPort": "6831" + "otlpEndpoint": "localhost:4317" }, "zipkinExporterOptions": { "url": "http://localhost:9411/api/v2/spans" diff --git a/internal/services/order_service/config/config.test.json b/internal/services/order_service/config/config.test.json index e6402e88..a4425c15 100644 --- a/internal/services/order_service/config/config.test.json +++ b/internal/services/order_service/config/config.test.json @@ -46,15 +46,15 @@ "httpPort": 15672 } }, - "OpenTelemetryOptions": { + "openTelemetryOptions": { "enable": true, "serviceName": "orders-service", "instrumentationName": "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice", "id": 3, "alwaysOnSampler": true, + "useStdout": false, "jaegerExporterOptions": { - "agentHost": "localhost", - "agentPort": "6831" + "otlpEndpoint": "localhost:4317" }, "zipkinExporterOptions": { "url": "http://localhost:9411/api/v2/spans" diff --git a/internal/services/order_service/go.mod b/internal/services/order_service/go.mod index 776edaf6..051daa60 100644 --- a/internal/services/order_service/go.mod +++ b/internal/services/order_service/go.mod @@ -9,7 +9,7 @@ require ( emperror.dev/errors v0.8.1 github.com/EventStore/EventStore-Client-Go v1.0.2 github.com/brianvoe/gofakeit/v6 v6.23.2 - github.com/elastic/go-elasticsearch/v8 v8.9.0 + github.com/elastic/go-elasticsearch/v8 v8.10.0 github.com/gavv/httpexpect/v2 v2.15.0 github.com/go-ozzo/ozzo-validation v3.6.0+incompatible github.com/go-playground/validator v9.31.0+incompatible @@ -27,11 +27,11 @@ require ( github.com/swaggo/echo-swagger v1.4.1 github.com/swaggo/swag v1.16.2 go.mongodb.org/mongo-driver v1.12.1 - go.opentelemetry.io/otel v1.17.0 - go.opentelemetry.io/otel/metric v1.17.0 - go.opentelemetry.io/otel/trace v1.17.0 + go.opentelemetry.io/otel v1.18.0 + go.opentelemetry.io/otel/metric v1.18.0 + go.opentelemetry.io/otel/trace v1.18.0 go.uber.org/fx v1.20.0 - google.golang.org/grpc v1.57.0 + google.golang.org/grpc v1.58.1 google.golang.org/protobuf v1.31.0 ) @@ -44,6 +44,7 @@ require ( github.com/KyleBanks/depth v1.2.1 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/hcsshim v0.11.0 // indirect github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 // indirect github.com/ahmetb/go-linq/v3 v3.2.0 // indirect github.com/ajg/form v1.5.1 // indirect @@ -56,12 +57,12 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/containerd/console v1.0.3 // indirect - github.com/containerd/containerd v1.7.5 // indirect + github.com/containerd/containerd v1.7.6 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker v24.0.5+incompatible // indirect + github.com/docker/docker v24.0.6+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/doug-martin/goqu/v9 v9.18.0 // indirect @@ -72,6 +73,7 @@ require ( github.com/ghodss/yaml v1.0.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.20.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/spec v0.20.9 // indirect @@ -93,6 +95,7 @@ require ( github.com/gookit/color v1.5.4 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/imkira/go-interpol v1.1.0 // indirect @@ -112,12 +115,13 @@ require ( github.com/joho/godotenv v1.5.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/kamva/mgm/v3 v3.5.0 // indirect - github.com/klauspost/compress v1.16.7 // indirect + github.com/klauspost/compress v1.17.0 // indirect github.com/labstack/gommon v0.4.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/lithammer/fuzzysearch v1.1.8 // indirect + github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -135,12 +139,13 @@ require ( github.com/nolleh/caption_json_formatter v0.2.2 // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc4 // indirect + github.com/opencontainers/image-spec v1.1.0-rc5 // indirect github.com/opencontainers/runc v1.1.9 // indirect github.com/openzipkin/zipkin-go v0.4.2 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.44.0 // indirect @@ -148,25 +153,30 @@ require ( github.com/rabbitmq/amqp091-go v1.8.1 // indirect github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 // indirect - github.com/redis/go-redis/v9 v9.0.5 // indirect + github.com/redis/go-redis/v9 v9.2.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/samber/lo v1.38.1 // indirect github.com/sanity-io/litter v1.5.5 // indirect github.com/sergi/go-diff v1.2.0 // indirect + github.com/shirou/gopsutil/v3 v3.23.8 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/afero v1.9.5 // indirect github.com/spf13/cast v1.5.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.16.0 // indirect - github.com/streadway/amqp v1.1.0 // indirect github.com/stretchr/objx v0.5.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/swaggo/files/v2 v2.0.0 // indirect - github.com/testcontainers/testcontainers-go v0.23.0 // indirect + github.com/testcontainers/testcontainers-go v0.24.1 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect - github.com/uptrace/bun v1.1.14 // indirect - github.com/uptrace/bun/driver/pgdriver v1.1.14 // indirect + github.com/uptrace/bun v1.1.16 // indirect + github.com/uptrace/bun/driver/pgdriver v1.1.16 // indirect + github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 // indirect + github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.34.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect @@ -183,18 +193,22 @@ require ( github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect github.com/yudai/gojsondiff v1.0.0 // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect - go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.43.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0 // indirect - go.opentelemetry.io/contrib/propagators/ot v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.40.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.17.0 // indirect - go.opentelemetry.io/otel/exporters/zipkin v1.17.0 // indirect - go.opentelemetry.io/otel/sdk v1.17.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.40.0 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 // indirect + go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 // indirect + go.opentelemetry.io/contrib/propagators/ot v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.41.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 // indirect + go.opentelemetry.io/otel/exporters/zipkin v1.18.0 // indirect + go.opentelemetry.io/otel/sdk v1.18.0 // indirect + go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect + go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/dig v1.17.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.25.0 // indirect + go.uber.org/zap v1.26.0 // indirect golang.org/x/crypto v0.13.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/mod v0.12.0 // indirect @@ -205,13 +219,15 @@ require ( golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gorm.io/driver/postgres v1.5.2 // indirect gorm.io/gorm v1.25.4 // indirect + gorm.io/plugin/opentelemetry v0.1.4 // indirect mellium.im/sasl v0.3.1 // indirect moul.io/http2curl/v2 v2.3.0 // indirect ) diff --git a/internal/services/order_service/go.sum b/internal/services/order_service/go.sum index 3d8dbc97..63142433 100644 --- a/internal/services/order_service/go.sum +++ b/internal/services/order_service/go.sum @@ -33,8 +33,8 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= -cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= +cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -83,8 +83,8 @@ github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA4 github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek= -github.com/Microsoft/hcsshim v0.10.0-rc.8/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= +github.com/Microsoft/hcsshim v0.11.0 h1:7EFNIY4igHEXUdj1zXgAyU3fLc7QfOKHbkldRVTBdiM= +github.com/Microsoft/hcsshim v0.11.0/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4= @@ -110,10 +110,12 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/brianvoe/gofakeit/v6 v6.23.2 h1:lVde18uhad5wII/f5RMVFLtdQNE0HaGFuBUXmYKk8i8= github.com/brianvoe/gofakeit/v6 v6.23.2/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8= -github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao= github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= -github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/caarlos0/env/v8 v8.0.0 h1:POhxHhSpuxrLMIdvTGARuZqR4Jjm8AYmoi/JKlcScs0= github.com/caarlos0/env/v8 v8.0.0/go.mod h1:7K4wMY9bH0esiXSSHlfHLX5xKGQMnkH5Fk4TDSSSzfo= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= @@ -138,8 +140,8 @@ github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMe github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.7.5 h1:i9T9XpAWMe11BHMN7pu1BZqOGjXaKTPyz2v+KYOZgkY= -github.com/containerd/containerd v1.7.5/go.mod h1:ieJNCSzASw2shSGYLHx8NAE7WsZ/gEigo5fQ78W5Zvw= +github.com/containerd/containerd v1.7.6 h1:oNAVsnhPoy4BTPQivLgTzI9Oleml9l/+eYIDYXRCYo8= +github.com/containerd/containerd v1.7.6/go.mod h1:SY6lrkkuJT40BVNO37tlYTSnKJnP5AXBc0fhx0q+TJ4= github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= @@ -163,12 +165,12 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/docker/cli v24.0.5+incompatible h1:WeBimjvS0eKdH4Ygx+ihVq1Q++xg36M/rMi4aXAvodc= -github.com/docker/cli v24.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY= +github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY= -github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE= +github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= @@ -180,16 +182,16 @@ github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:Htrtb github.com/elastic/elastic-transport-go/v8 v8.0.0-20230329154755-1a3c63de0db6/go.mod h1:87Tcz8IVNe6rVSLdBux1o/PEItLtyabHU3naC7IoqKI= github.com/elastic/elastic-transport-go/v8 v8.3.0 h1:DJGxovyQLXGr62e9nDMPSxRyWION0Bh6d9eCFBriiHo= github.com/elastic/elastic-transport-go/v8 v8.3.0/go.mod h1:87Tcz8IVNe6rVSLdBux1o/PEItLtyabHU3naC7IoqKI= -github.com/elastic/go-elasticsearch/v8 v8.9.0 h1:8xtmYjUkqtahl50E0Bg/wjKI7K63krJrrLipbNj/fCU= -github.com/elastic/go-elasticsearch/v8 v8.9.0/go.mod h1:NGmpvohKiRHXI0Sw4fuUGn6hYOmAXlyCphKpzVBiqDE= +github.com/elastic/go-elasticsearch/v8 v8.10.0 h1:ALg3DMxSrx07YmeMNcfPf7cFh1Ep2+Qa19EOXTbwr2k= +github.com/elastic/go-elasticsearch/v8 v8.10.0/go.mod h1:NGmpvohKiRHXI0Sw4fuUGn6hYOmAXlyCphKpzVBiqDE= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= -github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= @@ -215,6 +217,9 @@ github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= @@ -262,6 +267,8 @@ github.com/golang-migrate/migrate/v4 v4.16.2 h1:8coYbMKUyInrFk1lfGfRovTLAW7PhWp8 github.com/golang-migrate/migrate/v4 v4.16.2/go.mod h1:pfcJX4nPHaVdc5nmdCikFBWtm+UBpiZjRNNsyBbp0/o= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -306,6 +313,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= @@ -344,6 +352,8 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= @@ -434,8 +444,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= @@ -474,6 +484,9 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a h1:N9zuLhTvBSRt0gWSiJswwQ2HqDmtX/ZCDJURnKUt1Ik= +github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -498,6 +511,8 @@ github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mcuadros/go-defaults v1.2.0 h1:FODb8WSf0uGaY8elWJAkoLL0Ri6AlZ1bFlenk56oZtc= @@ -546,8 +561,8 @@ github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= -github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= +github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc95/go.mod h1:z+bZxa/+Tz/FmYVWkhUajJdzFeOqjc5vrqskhVyHGUM= github.com/opencontainers/runc v1.1.9 h1:XR0VIHTGce5eWPkaPesqTBrhW2yAcaraWfsEalNwQLM= @@ -571,6 +586,9 @@ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qR github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -595,8 +613,9 @@ github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fO github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJuQe5bzQ02jGd5Qcbgb97Flm7U= github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc= github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ= -github.com/redis/go-redis/v9 v9.0.5 h1:CuQcn5HIEeK7BgElubPP8CGtE0KakrnbBSTLjathl5o= github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= +github.com/redis/go-redis/v9 v9.2.0 h1:zwMdX0A4eVzse46YN18QhuDiM4uf3JmkOB4VZrdt5uI= +github.com/redis/go-redis/v9 v9.2.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= @@ -620,6 +639,12 @@ github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvW github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= +github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= @@ -678,15 +703,23 @@ github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04= github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8= -github.com/testcontainers/testcontainers-go v0.23.0 h1:ERYTSikX01QczBLPZpqsETTBO7lInqEP349phDOVJVs= -github.com/testcontainers/testcontainers-go v0.23.0/go.mod h1:3gzuZfb7T9qfcH2pHpV4RLlWrPjeWNQah6XlYQ32c4I= +github.com/testcontainers/testcontainers-go v0.24.1 h1:gJdZuQIVWnMJTo+CmQMEP7/CAagNk/0jbcUPn3OWvD8= +github.com/testcontainers/testcontainers-go v0.24.1/go.mod h1:MGBiAkCm86yXQoCiipmQCqZLVdk1uFqtMqaU1Or0MRk= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= -github.com/uptrace/bun v1.1.14 h1:S5vvNnjEynJ0CvnrBOD7MIRW7q/WbtvFXrdfy0lddAM= -github.com/uptrace/bun v1.1.14/go.mod h1:RHk6DrIisO62dv10pUOJCz5MphXThuOTpVNYEYv7NI8= -github.com/uptrace/bun/driver/pgdriver v1.1.14 h1:V2Etm7mLGS3mhx8ddxZcUnwZLX02Jmq9JTlo0sNVDhA= -github.com/uptrace/bun/driver/pgdriver v1.1.14/go.mod h1:D4FjWV9arDYct6sjMJhFoyU71SpllZRHXFRRP2Kd0Kw= +github.com/uptrace/bun v1.1.16 h1:cn9cgEMFwcyYRsQLfxCRMUxyK1WaHwOVrR3TvzEFZ/A= +github.com/uptrace/bun v1.1.16/go.mod h1:7HnsMRRvpLFUcquJxp22JO8PsWKpFQO/gNXqqsuGWg8= +github.com/uptrace/bun/driver/pgdriver v1.1.16 h1:b/NiSXk6Ldw7KLfMLbOqIkm4odHd7QiNOCPLqPFJjK4= +github.com/uptrace/bun/driver/pgdriver v1.1.16/go.mod h1:Rmfbc+7lx1z/umjMyAxkOHK81LgnGj71XC5YpA6k1vU= +github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 h1:CNznWHkrbA6o1q2H/BsH4tIHf4zbKNtndeoV+AH8z0U= +github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2/go.mod h1:7YSrHCmYPHIXjTWnKSU7EGT0TFEcm3WwSeQquwCGg38= +github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 h1:uyrW06oJi4iWvhjPLVfk4qrSP2Zm0AMozKKDmp6i4pE= +github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2/go.mod h1:PMAs2dNxP55lgt6xu0if+Jasm6s+Xpmqn6ev1NyDfnI= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -738,6 +771,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY= go.mongodb.org/mongo-driver v1.12.1 h1:nLkghSU8fQNaK7oUmDhQFsnrtcoNy7Z6LVFKsEecqgE= @@ -748,32 +783,38 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.43.0 h1:pcWR7mkuO5XMK3f0KeGpr70OTR9/ikPk0D1hHEd5dp4= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.43.0/go.mod h1:azTPpa9PvRDSNU/lQbe2CRDQoTcau5moOjS4EzhpyAY= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0 h1:7XZai4VhA473clBrOqqHdjHBImGfyEtv0qW4nnn/kAo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0/go.mod h1:1WpsUwjQrUJSNugfMlPn0rPRJ9Do7wwBgTBPK7MLiS4= -go.opentelemetry.io/contrib/propagators/b3 v1.18.0 h1:hhSlPVi9AQwOmbMmptPNLfRZOLgENdRM2kb7z9LFe1A= -go.opentelemetry.io/contrib/propagators/b3 v1.18.0/go.mod h1:qtt+pEu23D7UVP+j33G4i7LopmVu8/6/IwGu3hEm100= -go.opentelemetry.io/contrib/propagators/ot v1.18.0 h1:VmzxO7BjUU6oo0ChcKuGdKaSR0vchPxwahHZl64zVUM= -go.opentelemetry.io/contrib/propagators/ot v1.18.0/go.mod h1:5VwcOJ7OjS0uPxaxuwKHwJtkt+EAC+cgjXleXMe51z4= -go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM= -go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0= -go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4= -go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI= -go.opentelemetry.io/otel/exporters/prometheus v0.40.0 h1:9h6lCssr1j5aYVvWT6oc+ERB6R034zmsHjBRLyxrAR8= -go.opentelemetry.io/otel/exporters/prometheus v0.40.0/go.mod h1:5USWZ0ovyQB5CIM3IO3bGRSoDPMXiT3t+15gu8Zo9HQ= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.17.0 h1:Ut6hgtYcASHwCzRHkXEtSsM251cXJPW+Z9DyLwEn6iI= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.17.0/go.mod h1:TYeE+8d5CjrgBa0ZuRaDeMpIC1xZ7atg4g+nInjuSjc= -go.opentelemetry.io/otel/exporters/zipkin v1.17.0 h1:oi5+xMN3pflqWSd4EX6FiO+Cn3KbFBBzeQmD5LMIf0c= -go.opentelemetry.io/otel/exporters/zipkin v1.17.0/go.mod h1:pNir+S6/f0HFGfbXhobXLTFu60KtAzw8aGSUpt9A6VU= -go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc= -go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o= -go.opentelemetry.io/otel/sdk v1.17.0 h1:FLN2X66Ke/k5Sg3V623Q7h7nt3cHXaW1FOvKKrW0IpE= -go.opentelemetry.io/otel/sdk v1.17.0/go.mod h1:U87sE0f5vQB7hwUoW98pW5Rz4ZDuCFBZFNUBlSgmDFQ= -go.opentelemetry.io/otel/sdk/metric v0.40.0 h1:qOM29YaGcxipWjL5FzpyZDpCYrDREvX0mVlmXdOjCHU= -go.opentelemetry.io/otel/sdk/metric v0.40.0/go.mod h1:dWxHtdzdJvg+ciJUKLTKwrMe5P6Dv3FyDbh8UkfgkVs= -go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ= -go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY= +go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 h1:9n9+SOwuCyZ0L8SbQYjZ5H+GKojHN3Kl8pBLwBUQqhk= +go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0/go.mod h1:Wa9/q2K5L+ftWke2iekGNqVzwBWqyhI5OhtHKU7Qe04= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 h1:M5oKw7m89PAciR2j41n5Zq9rShK14iUadvCRy7nkSIo= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0/go.mod h1:JH6FxBlkXo/cYoU/m65W5dOQ6sqPL+jHtSJaSE7/+XQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 h1:b8xjZxHbLrXAum4SxJd1Rlm7Y/fKaB+6ACI7/e5EfSA= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0/go.mod h1:1ei0a32xOGkFoySu7y1DAHfcuIhC0pNZpvY2huXuMy4= +go.opentelemetry.io/contrib/propagators/b3 v1.19.0 h1:ulz44cpm6V5oAeg5Aw9HyqGFMS6XM7untlMEhD7YzzA= +go.opentelemetry.io/contrib/propagators/b3 v1.19.0/go.mod h1:OzCmE2IVS+asTI+odXQstRGVfXQ4bXv9nMBRK0nNyqQ= +go.opentelemetry.io/contrib/propagators/ot v1.19.0 h1:vODRLMlKN4ApM8ri0UDk8nnEeISuwxpf67sE7PmOHhE= +go.opentelemetry.io/contrib/propagators/ot v1.19.0/go.mod h1:S2Uc7th2ZmLiHu0lrCmDCgTQ/y5Nbbis+TNjR1jjm4Q= +go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= +go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 h1:IAtl+7gua134xcV3NieDhJHjjOVeJhXAnYf/0hswjUY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0/go.mod h1:w+pXobnBzh95MNIkeIuAKcHe/Uu/CX2PKIvBP6ipKRA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32ay7mJG2leczfREEhoW3VfSZIvHaB+gvVo1o8DQ8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4= +go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= +go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes= +go.opentelemetry.io/otel/exporters/zipkin v1.18.0 h1:ZqrHgvega5NIiScTiVrtpZSpEmjUdwzkhuuCEIMAp+s= +go.opentelemetry.io/otel/exporters/zipkin v1.18.0/go.mod h1:C80yIYcSceQipAZb4Ah11EE/yERlyc1MtqJG2xP7p+s= +go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= +go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= +go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= +go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= +go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= +go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= +go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= +go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -799,8 +840,8 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -914,8 +955,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -948,6 +989,7 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -975,6 +1017,7 @@ golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1000,8 +1043,11 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -1166,8 +1212,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13 h1:U7+wNaVuSTaUqNvK2+osJ9ejEZxbjHHk8F2b6Hpx0AE= +google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:RdyHbowztCGQySiCvQPgWQWgWhGnouTdCflKoDBt32U= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1184,8 +1234,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= +google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1233,8 +1283,12 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0= gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8= +gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c= +gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I= gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/plugin/opentelemetry v0.1.4 h1:7p0ocWELjSSRI7NCKPW2mVe6h43YPini99sNJcbsTuc= +gorm.io/plugin/opentelemetry v0.1.4/go.mod h1:tndJHOdvPT0pyGhOb8E2209eXJCUxhC5UpKw7bGVWeI= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/scripts/update-dependencies.sh b/scripts/update-dependencies.sh new file mode 100644 index 00000000..924ceae7 --- /dev/null +++ b/scripts/update-dependencies.sh @@ -0,0 +1,13 @@ +# In a bash script, set -e is a command that enables the "exit immediately" option. When this option is set, the script will terminate immediately if any command within the script exits with a non-zero status (indicating an error). +set -e + +readonly service="$1" + +echo "start upgrading packages in $service" + +if [ "$service" = "pkg" ]; then + cd "./internal/pkg" && go get -u -t -d -v ./... && go mod tidy +# Check if input is not empty or null +elif [ -n "$service" ]; then + cd "./internal/services/$service" && go get -u -t -d -v ./... && go mod tidy +fi From f2eb09ef6a6b8431458ec3ec28b9014e99bcce2c Mon Sep 17 00:00:00 2001 From: mehdihadeli Date: Mon, 25 Sep 2023 01:29:30 +0330 Subject: [PATCH 02/15] refactor: :recycle: refactor tracing and metrics --- deployments/docker-compose/.env | 45 +- ...cker-compose.infrastructure-collector.yaml | 338 ++++++++++++ .../docker-compose.infrastructure.yaml | 126 +++-- .../docker-compose/monitoring/grafana.yaml | 16 + .../docker-compose/monitoring/prometheus.yml | 65 ++- .../docker-compose/otel-collector-config.yaml | 21 +- .../otelcollector/otelcol-config-extras.yml | 4 + .../otelcollector/otelcol-config.yml | 53 ++ .../otelcollector/otelcol-observability.yml | 49 ++ internal/pkg/.env | 0 internal/pkg/bun/postgres/bun_postgres.go | 2 +- internal/pkg/config.development.json | 85 +++ internal/pkg/config/config_helper.go | 95 +++- .../pkg/config/environemnt/environment.go | 62 ++- internal/pkg/go.mod | 19 +- internal/pkg/go.sum | 34 +- internal/pkg/gorm_postgres/db.go | 6 + internal/pkg/gorm_postgres/gorm_options.go | 13 +- .../pkg/gorm_postgres/gorm_postgres_fx.go | 12 +- internal/pkg/gorm_postgres/health.go | 4 +- internal/pkg/grpc/server.go | 14 +- internal/pkg/health/{ => contracts}/check.go | 3 +- internal/pkg/health/{ => contracts}/health.go | 6 +- .../health/{ => contracts}/health_params.go | 2 +- internal/pkg/health/{ => contracts}/status.go | 2 +- internal/pkg/health/health_endpoint.go | 19 +- internal/pkg/health/health_fx.go | 2 +- internal/pkg/health/service.go | 20 +- internal/pkg/health/unhealthy.go | 20 +- .../http/custom_echo/contracts/echoserver.go | 23 + .../{ => contracts}/route_builder.go | 2 +- .../pkg/http/custom_echo/custom_echo_fx.go | 15 +- internal/pkg/http/custom_echo/echo_server.go | 98 ++-- .../custom_echo/middlewares/log/config.go | 27 + .../middlewares/log/log_middleware.go | 79 ++- .../middlewares/otel_metrics/config.go | 17 + .../otel_metrics/request_status_middleware.go | 9 +- .../middlewares/otel_metrics/v0/prometheus.go | 518 ++++++++++++++++++ .../middlewares/otel_metrics/v1/metric.go | 193 +++++++ .../middlewares/otel_metrics/v1/middleware.go | 49 ++ .../middlewares/otel_metrics/v1/view.go | 26 + .../middlewares/otel_metrics/v2/otel-meter.go | 446 +++++++++++++++ .../tracing/utils.go => utils/tracing.go} | 14 +- internal/pkg/logger/config/log_options.go | 1 + internal/pkg/logger/external/fxlog/fx.go | 2 +- internal/pkg/logger/external/gromlog/gorm.go | 2 +- internal/pkg/logger/logrous/logrous_logger.go | 20 +- internal/pkg/logger/zap/zap_logger.go | 7 +- internal/pkg/mongodb/health.go | 4 +- internal/pkg/mongodb/mongo_fx.go | 4 +- internal/pkg/mongodb/mongo_options.go | 21 +- internal/pkg/mongodb/mongodb.go | 7 +- .../pkg/otel/config/open_telemtry_options.go | 46 -- internal/pkg/otel/metrics/custom_meter.go | 22 + internal/pkg/otel/metrics/metrics.go | 279 ++++++++-- internal/pkg/otel/metrics/metrics_fx.go | 92 ++++ internal/pkg/otel/metrics/metrics_options.go | 41 ++ internal/pkg/otel/metrics/metrics_test.go | 69 +++ internal/pkg/otel/otel_fx.go | 107 ---- internal/pkg/otel/tracing/tracing.go | 336 ++++++++---- internal/pkg/otel/tracing/tracing_fx.go | 60 ++ internal/pkg/otel/tracing/tracing_options.go | 46 ++ .../consumer/rabbitmq_consumer_test.go | 7 +- internal/pkg/rabbitmq/health.go | 4 +- .../producer/rabbitmq_producer_test.go | 5 +- internal/pkg/rabbitmq/rabbitmq_fx.go | 4 +- internal/pkg/redis/health.go | 4 +- internal/pkg/redis/redis.go | 5 + internal/pkg/redis/redis_fx.go | 26 +- internal/pkg/redis/redis_options.go | 11 +- .../config/config.development.json | 37 +- .../config/config.test.json | 37 +- internal/services/catalog_read_service/go.mod | 13 +- internal/services/catalog_read_service/go.sum | 32 +- .../products_module_configurator.go | 6 +- .../catalogs/catalogs_configurator.go | 4 +- .../catalogs/catalogs_configurator_swagger.go | 2 +- .../infrastructure/infrastructure_fx.go | 5 +- .../config/config.development.json | 35 +- .../config/config.test.json | 27 +- .../services/catalog_write_service/go.mod | 13 +- .../services/catalog_write_service/go.sum | 34 +- .../products_module_configurator.go | 6 +- .../v1/endpoints/create_product_endpoint.go | 11 +- .../internal/products/products_fx.go | 46 +- .../internal/shared/app/test/test_app.go | 6 +- .../catalogs/catalogs_configurator.go | 38 +- .../catalogs_configurator_migration.go | 21 +- .../catalogs/catalogs_configurator_swagger.go | 2 +- .../infrastructure/infrastructure_fx.go | 8 +- .../infrastructure/infrastructure_test_fx.go | 10 - .../integration/integration_test_fixture.go | 9 - .../config/config.development.json | 39 +- .../order_service/config/config.test.json | 39 +- internal/services/order_service/go.mod | 1 + internal/services/order_service/go.sum | 2 + .../orders_module_configurator.go | 8 +- .../infrastructure/infrastructure_fx.go | 6 +- .../orders/orders_configurator.go | 4 +- .../orders/orders_configurator_swagger.go | 2 +- scripts/service-reset.ps1 | 2 + 101 files changed, 3645 insertions(+), 745 deletions(-) create mode 100644 deployments/docker-compose/docker-compose.infrastructure-collector.yaml create mode 100644 deployments/docker-compose/monitoring/grafana.yaml create mode 100644 deployments/docker-compose/otelcollector/otelcol-config-extras.yml create mode 100644 deployments/docker-compose/otelcollector/otelcol-config.yml create mode 100644 deployments/docker-compose/otelcollector/otelcol-observability.yml create mode 100644 internal/pkg/.env create mode 100644 internal/pkg/config.development.json rename internal/pkg/health/{ => contracts}/check.go (89%) rename internal/pkg/health/{ => contracts}/health.go (54%) rename internal/pkg/health/{ => contracts}/health_params.go (85%) rename internal/pkg/health/{ => contracts}/status.go (94%) create mode 100644 internal/pkg/http/custom_echo/contracts/echoserver.go rename internal/pkg/http/custom_echo/{ => contracts}/route_builder.go (96%) create mode 100644 internal/pkg/http/custom_echo/middlewares/log/config.go create mode 100644 internal/pkg/http/custom_echo/middlewares/otel_metrics/config.go create mode 100644 internal/pkg/http/custom_echo/middlewares/otel_metrics/v0/prometheus.go create mode 100644 internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/metric.go create mode 100644 internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/middleware.go create mode 100644 internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/view.go create mode 100644 internal/pkg/http/custom_echo/middlewares/otel_metrics/v2/otel-meter.go rename internal/pkg/http/custom_echo/{otel/tracing/utils.go => utils/tracing.go} (84%) delete mode 100644 internal/pkg/otel/config/open_telemtry_options.go create mode 100644 internal/pkg/otel/metrics/custom_meter.go create mode 100644 internal/pkg/otel/metrics/metrics_fx.go create mode 100644 internal/pkg/otel/metrics/metrics_options.go create mode 100644 internal/pkg/otel/metrics/metrics_test.go delete mode 100644 internal/pkg/otel/otel_fx.go create mode 100644 internal/pkg/otel/tracing/tracing_fx.go create mode 100644 internal/pkg/otel/tracing/tracing_options.go delete mode 100644 internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_test_fx.go create mode 100644 scripts/service-reset.ps1 diff --git a/deployments/docker-compose/.env b/deployments/docker-compose/.env index 91bcd9ee..995bdc94 100644 --- a/deployments/docker-compose/.env +++ b/deployments/docker-compose/.env @@ -22,8 +22,7 @@ PROMETHEUS_PORT=9090 PROMETHEUS_HOST_PORT=9090 KIBANA_PORT=5601 KIBANA_HOST_PORT=5601 -ELASTIC_PORT=9200 -ELASTIC_HOST_PORT=9200 + EVENTSTORE_PORT=2113 EVENTSTORE_HOST_PORT=2113 EVENTSTORE_TCP_HOST_PORT=1113 @@ -44,3 +43,45 @@ CUSTOMERS_SVC_PORT=8000 ORDERS_SVC_PORT=5000 IDENTITY_SVC_PORT=7000 +# ****************** +# Dependent Services +# ****************** +# Kafka +KAFKA_SERVICE_PORT=9092 + +# Redis +REDIS_PORT=6379 + +# Elastic +ELASTIC_PORT=9200 +ELASTIC_HOST_PORT=9200 + +# ******************** +# Telemetry Components +# ******************** +# Grafana +GRAFANA_SERVICE_PORT=3000 +GRAFANA_SERVICE_HOST=grafana + +# Jaeger +JAEGER_SERVICE_PORT=16686 +JAEGER_SERVICE_HOST=jaeger + +# Prometheus +PROMETHEUS_SERVICE_PORT=9090 +PROMETHEUS_SERVICE_HOST=prometheus +PROMETHEUS_ADDR=${PROMETHEUS_SERVICE_HOST}:${PROMETHEUS_SERVICE_PORT} + + +# OpenTelemetry Collector +OTEL_COLLECTOR_HOST=otelcol +OTEL_COLLECTOR_PORT_GRPC=4317 +OTEL_COLLECTOR_PORT_HTTP=4318 +OTEL_EXPORTER_OTLP_ENDPOINT=http://${OTEL_COLLECTOR_HOST}:${OTEL_COLLECTOR_PORT_GRPC} +PUBLIC_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:8080/otlp-http/v1/traces + +# OpenTelemetry Resource Definitions +OTEL_RESOURCE_ATTRIBUTES="service.namespace=ecommerce" + +# Metrics Temporality +OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=cumulative diff --git a/deployments/docker-compose/docker-compose.infrastructure-collector.yaml b/deployments/docker-compose/docker-compose.infrastructure-collector.yaml new file mode 100644 index 00000000..436db1ee --- /dev/null +++ b/deployments/docker-compose/docker-compose.infrastructure-collector.yaml @@ -0,0 +1,338 @@ +# Ref:https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/examples/demo/docker-compose.yaml +# https://github.com/open-telemetry/opentelemetry-demo/blob/main/docker-compose.yml + +version: "3.8" +name: go-ecommerce-microservices + +services: + rabbitmq: + image: rabbitmq:management + container_name: rabbitmq + pull_policy: if_not_present + restart: unless-stopped + ports: + - ${RABBITMQ_HOST_PORT:-5672}:${RABBITMQ_PORT:-5672} + - ${RABBITMQ_HOST_API_PORT:-15672}:${RABBITMQ_API_PORT:-15672} + # volumes: + # - rabbitmq:/var/lib/rabbitmq + networks: + - ecommerce + + # containers monitoring + cadvisor: + image: gcr.io/cadvisor/cadvisor:latest + restart: unless-stopped + ports: + - "9091:8080" + # network_mode: host + volumes: + - /:/rootfs:ro + - /var/run:/var/run:ro + - /sys:/sys:ro + - /var/lib/docker/:/var/lib/docker:ro + - /dev/disk/:/dev/disk:ro + devices: + - /dev/kmsg + networks: + - ecommerce + + # prometheus dashboard: http://localhost:9090 + # prometheus internal metrics: http://localhost:9090/metrics + # https://prometheus.io/docs/prometheus/latest/getting_started/ + # https://prometheus.io/docs/guides/go-application/ + prometheus: + image: prom/prometheus:latest + pull_policy: if_not_present + container_name: prometheus + restart: unless-stopped + user: root + ports: + - ${PROMETHEUS_HOST_PORT:-9090}:${PROMETHEUS_PORT:-9090} + command: + - --config.file=/etc/prometheus/prometheus.yml + volumes: + - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro + networks: + - ecommerce + + otelcol: + image: otel/opentelemetry-collector-contrib:latest + container_name: otel-col + pull_policy: if_not_present + deploy: + resources: + limits: + memory: 125M + restart: unless-stopped + command: [ "--config=/etc/otelcol-config.yml", "--config=/etc/otelcol-observability.yml", "--config=/etc/otelcol-config-extras.yml" ] + volumes: + - ./otelcollector/otelcol-config.yml:/etc/otelcol-config.yml + - ./otelcollector/otelcol-observability.yml:/etc/otelcol-observability.yml + - ./otelcollector/otelcol-config-extras.yml:/etc/otelcol-config-extras.yml + ports: + - "4317:4317" # OTLP over gRPC receiver + - "4318:4318" # OTLP over HTTP receiver + - "8889:8889" # Prometheus exporter metrics + - "8888:8888" # Prometheus metrics exposed by the collector + - "13133:13133" # health_check extension + - "55679:55679" # zpages extension + - "1888:1888" # pprof extension + depends_on: + - jaeger + - prometheus + + # node_exporter will use for gathering metrics on the system level with its own /metrics endpoint like cpu, ram, ... + # https://prometheus.io/docs/guides/node-exporter/ + node_exporter: + container_name: node_exporter + pull_policy: if_not_present + restart: unless-stopped + image: prom/node-exporter + ports: + - "9100:9100" + networks: + - ecommerce + + grafana: + image: grafana/grafana + pull_policy: if_not_present + container_name: grafana + restart: unless-stopped + volumes: + - ./monitoring/grafana.yaml:/etc/grafana/provisioning/datasources/datasource.yaml + ports: + - ${GRAFANA_HOST_PORT:-3000}:${GRAFANA_PORT:-3000} + networks: + - ecommerce + + postgres: + image: postgres:latest + pull_policy: if_not_present + container_name: postgres + restart: unless-stopped + ports: + - ${POSTGRES_HOST_PORT:-5432}:${POSTGRES_PORT:-5432} + #https://docs.docker.com/compose/environment-variables/env-file/#parameter-expansion + environment: + - POSTGRES_USER=${POSTGRES_USER:-postgres} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-postgres} + networks: + - ecommerce + + # https://developer.redis.com/howtos/quick-start + # redis-stack is a image with redis modules enabled like JSON module + redis: + image: redis/redis-stack:latest + pull_policy: if_not_present + restart: unless-stopped + container_name: redis + ports: + - "6379:6379" + networks: + - ecommerce + + # zookeeper: + # image: confluentinc/cp-zookeeper:7.0.1 + # hostname: zookeeper + # container_name: zookeeper + # restart: unless-stopped + # ports: + # - "2181:2181" + # environment: + # ZOOKEEPER_CLIENT_PORT: 2181 + # ZOOKEEPER_TICK_TIME: 2000 + # networks: + # - ecommerce + + # kafka: + # image: confluentinc/cp-kafka:7.0.1 + # hostname: kafka + # container_name: kafka + # restart: unless-stopped + # depends_on: + # - zookeeper + # ports: + # - "9092:9092" + # environment: + # KAFKA_BROKER_ID: 1 + # KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181' + # KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT + # KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 + # KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + # ADVERTISED_HOST_NAME: kafka + # KAFKA_ADVERTISED_HOSTNAME: 127.0.0.1 + # networks: + # - ecommerce + + # kafka-ui: + # image: provectuslabs/kafka-ui + # container_name: kafka-ui + # ports: + # - "8080:8080" + # restart: always + # environment: + # - KAFKA_CLUSTERS_0_NAME=local + # - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:9092 + # - KAFKA_CLUSTERS_0_ZOOKEEPER=zookeeper:2181 + + # kafdrop: + # image: obsidiandynamics/kafdrop + # container_name: kafdrop + # ports: + # - '9000:9000' + # environment: + # - 'KAFKA_BROKERCONNECT=' + # - 'JVM_OPTS=-Xms32M -Xmx64M' + # - SERVER_SERVLET_CONTEXTPATH=/ + + mongo: + image: mongo + pull_policy: if_not_present + container_name: mongo + restart: unless-stopped + # https://docs.docker.com/compose/environment-variables/env-file/#parameter-expansion + environment: + - MONGO_INITDB_ROOT_USERNAME=${MONGO_USER:-admin} + - MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASS:-admin} + ports: + - ${MONGO_HOST_PORT:-27017}:${MONGO_PORT:-27017} + networks: + - ecommerce + + # https://www.jaegertracing.io/docs/1.38/apis/#opentelemetry-protocol-stable + # https://deploy-preview-1892--opentelemetry.netlify.app/blog/2022/jaeger-native-otlp/ + # https://www.jaegertracing.io/docs/1.49/deployment/ + # https://www.jaegertracing.io/docs/1.49/getting-started/ + # https://opentelemetry.io/docs/instrumentation/go/exporters/ + # https://opentelemetry.io/docs/specs/otlp/ + jaeger: + image: jaegertracing/all-in-one:latest + container_name: jaeger + pull_policy: if_not_present + restart: unless-stopped + command: + - "--memory.max-traces" + - "10000" + - "--query.base-path" + - "/jaeger/ui" + - "--prometheus.server-url" + - "http://${PROMETHEUS_ADDR}" + environment: + - COLLECTOR_ZIPKIN_HOST_PORT=:9411 + - COLLECTOR_OTLP_ENABLED=true + # Store metrics in PROMETHEUS storage instead of in-memory storage + - METRICS_STORAGE_TYPE=prometheus + - PROMETHEUS_SERVER_URL=http:${PROMETHEUS_ADDR} + # # Jaeger uses Elasticsearch as span storage instead of in-memory storage + # - SPAN_STORAGE_TYPE=elasticsearch + # - ES_SERVER_URLS=http://elastic_search:${ELASTIC_PORT:-9200} + # - ES_VERSION=8 + ports: + - "16686:16686" # Jaeger UI port + - "4320:4317" # OTLP gRPC default port - for prevent duplicate expose this port that will expose also by `otel-collector` we not expose it on `4317` - `4320` could use by the app through otlptracegrpc + - "4321:4318" # OTLP Http default port - for prevent duplicate expose this port that will expose also by `otel-collector` we not expose it on `4318` - `4321` could use by the app through otlptracehttp + networks: + - ecommerce + + zipkin: + image: openzipkin/zipkin:latest + pull_policy: if_not_present + restart: unless-stopped + container_name: zipkin + ports: + - "9411:9411" + networks: + - ecommerce + + # https://developers.eventstore.com/server/v21.10/installation.html#insecure-single-node + # https://hub.docker.com/r/eventstore/eventstore/tags + # https://stackoverflow.com/questions/65272764/ports-are-not-available-listen-tcp-0-0-0-0-50070-bind-an-attempt-was-made-to + # EVENTSTORE_MEM_DB=true, it tells the EventStoreDB container to use an in-memory database, which means that any data stored in EventStoreDB will not be persisted between container restarts. Once the container is stopped or restarted, all data will be lost. + eventstore: + image: eventstore/eventstore:latest + pull_policy: if_not_present + container_name: eventstore + restart: unless-stopped + environment: + - EVENTSTORE_CLUSTER_SIZE=1 + - EVENTSTORE_RUN_PROJECTIONS=All + - EVENTSTORE_START_STANDARD_PROJECTIONS=false + - EVENTSTORE_EXT_TCP_PORT=1113 + - EVENTSTORE_HTTP_PORT=2113 + - EVENTSTORE_INSECURE=true + - EVENTSTORE_ENABLE_EXTERNAL_TCP=true + - EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=true + - EVENTSTORE_MEM_DB=true + ports: + - ${EVENTSTORE_TCP_HOST_PORT:-1113}:${EVENTSTORE_TCP_PORT:-1113} + - ${EVENTSTORE_HOST_PORT:-2113}:${EVENTSTORE_PORT:-2113} + volumes: + - type: volume + source: eventstore-volume-data + target: /var/lib/eventstore + - type: volume + source: eventstore-volume-logs + target: /var/log/eventstore + networks: + - ecommerce + + # # https://stackoverflow.com/questions/67791781/how-to-configure-apm-server-to-docker-compose-file + # # https://www.elastic.co/guide/en/apm/guide/current/open-telemetry.html + # apm-server: + # image: docker.elastic.co/apm/apm-server:latest + # cap_add: ["CHOWN", "DAC_OVERRIDE", "SETGID", "SETUID"] + # cap_drop: ["ALL"] + # ports: + # - 8200:8200 + # command: > + # apm-server -e + # -E apm-server.rum.enabled=true + # -E setup.kibana.host=kibana:5601 + # -E setup.template.settings.index.number_of_replicas=0 + # -E apm-server.kibana.enabled=true + # -E apm-server.kibana.host=kibana:5601 + # -E output.elasticsearch.hosts=["elasticsearch:9200"] + + # elasticsearch: + # container_name: elastic_search + # restart: unless-stopped + # image: elasticsearch:8.5.2 + # environment: + # - discovery.type=single-node + # - bootstrap.memory_lock=true + # - xpack.monitoring.enabled=true + # - xpack.watcher.enabled=false + # - "ES_JAVA_OPTS=-Xms512m -Xmx512m" + # ulimits: + # memlock: + # soft: -1 + # hard: -1 + # volumes: + # - elastic-data:/usr/share/elasticsearch/data + # ports: + # - ${ELASTIC_HOST_PORT:-9200}:${ELASTIC_PORT:-9200} + # - 9300:9300 + # networks: + # - ecommerce + + # kibana: + # image: kibana:8.5.2 + # container_name: kibana + # restart: unless-stopped + # environment: + # - ELASTICSEARCH_HOSTS=http://elastic_search:9200 + # ports: + # - ${KIBANA_HOST_PORT:-5601}:${KIBANA_PORT:-5601} + # networks: + # - ecommerce + # depends_on: + # - elasticsearch + +volumes: + eventstore-volume-data: + eventstore-volume-logs: + elastic-data: + +networks: + ecommerce: + name: ecommerce diff --git a/deployments/docker-compose/docker-compose.infrastructure.yaml b/deployments/docker-compose/docker-compose.infrastructure.yaml index f2200e6d..4644d93e 100644 --- a/deployments/docker-compose/docker-compose.infrastructure.yaml +++ b/deployments/docker-compose/docker-compose.infrastructure.yaml @@ -1,3 +1,6 @@ +# Ref:https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/examples/demo/docker-compose.yaml +# https://github.com/open-telemetry/opentelemetry-demo/blob/main/docker-compose.yml + version: "3.8" name: go-ecommerce-microservices @@ -6,7 +9,7 @@ services: image: rabbitmq:management container_name: rabbitmq pull_policy: if_not_present - restart: on-failure + restart: unless-stopped ports: - ${RABBITMQ_HOST_PORT:-5672}:${RABBITMQ_PORT:-5672} - ${RABBITMQ_HOST_API_PORT:-15672}:${RABBITMQ_API_PORT:-15672} @@ -15,11 +18,15 @@ services: networks: - ecommerce + # prometheus dashboard: http://localhost:9090 + # prometheus internal metrics: http://localhost:9090/metrics + # https://prometheus.io/docs/prometheus/latest/getting_started/ + # https://prometheus.io/docs/guides/go-application/ prometheus: image: prom/prometheus:latest pull_policy: if_not_present container_name: prometheus - restart: on-failure + restart: unless-stopped user: root ports: - ${PROMETHEUS_HOST_PORT:-9090}:${PROMETHEUS_PORT:-9090} @@ -30,21 +37,25 @@ services: networks: - ecommerce + # node_exporter will use for gathering metrics on the system level with its own /metrics endpoint like cpu, ram, ... + # https://prometheus.io/docs/guides/node-exporter/ node_exporter: container_name: node_exporter pull_policy: if_not_present - restart: on-failure + restart: unless-stopped image: prom/node-exporter ports: - - "9101:9100" + - "9100:9100" networks: - ecommerce grafana: - container_name: grafana - pull_policy: if_not_present - restart: on-failure image: grafana/grafana + pull_policy: if_not_present + container_name: grafana + restart: unless-stopped + volumes: + - ./monitoring/grafana.yaml:/etc/grafana/provisioning/datasources/datasource.yaml ports: - ${GRAFANA_HOST_PORT:-3000}:${GRAFANA_PORT:-3000} networks: @@ -54,7 +65,7 @@ services: image: postgres:latest pull_policy: if_not_present container_name: postgres - restart: on-failure + restart: unless-stopped ports: - ${POSTGRES_HOST_PORT:-5432}:${POSTGRES_PORT:-5432} #https://docs.docker.com/compose/environment-variables/env-file/#parameter-expansion @@ -69,7 +80,7 @@ services: redis: image: redis/redis-stack:latest pull_policy: if_not_present - restart: on-failure + restart: unless-stopped container_name: redis ports: - "6379:6379" @@ -80,7 +91,7 @@ services: # image: confluentinc/cp-zookeeper:7.0.1 # hostname: zookeeper # container_name: zookeeper - # restart: on-failure + # restart: unless-stopped # ports: # - "2181:2181" # environment: @@ -93,7 +104,7 @@ services: # image: confluentinc/cp-kafka:7.0.1 # hostname: kafka # container_name: kafka - # restart: on-failure + # restart: unless-stopped # depends_on: # - zookeeper # ports: @@ -134,7 +145,7 @@ services: image: mongo pull_policy: if_not_present container_name: mongo - restart: on-failure + restart: unless-stopped # https://docs.docker.com/compose/environment-variables/env-file/#parameter-expansion environment: - MONGO_INITDB_ROOT_USERNAME=${MONGO_USER:-admin} @@ -154,53 +165,41 @@ services: image: jaegertracing/all-in-one:latest container_name: jaeger pull_policy: if_not_present + restart: unless-stopped + command: + - "--memory.max-traces" + - "10000" + - "--query.base-path" + - "/jaeger/ui" + - "--prometheus.server-url" + - "http://${PROMETHEUS_ADDR}" environment: - COLLECTOR_ZIPKIN_HOST_PORT=:9411 - COLLECTOR_OTLP_ENABLED=true + # Store metrics in PROMETHEUS storage instead of in-memory storage - METRICS_STORAGE_TYPE=prometheus - - PROMETHEUS_SERVER_URL=http://prometheus:9090 + - PROMETHEUS_SERVER_URL=http:${PROMETHEUS_ADDR} +# # Jaeger uses Elasticsearch as span storage instead of in-memory storage +# - SPAN_STORAGE_TYPE=elasticsearch +# - ES_SERVER_URLS=http://elastic_search:${ELASTIC_PORT:-9200} +# - ES_VERSION=8 ports: - - "6831:6831/udp" - - "6832:6832/udp" - - "5778:5778" - - "16686:16686" - - "4317:4317" - - "4318:4318" - - "14250:14250" - - "14268:14268" - - "14269:14269" + - "16686:16686" # Jaeger UI port + - "4320:4317" # OTLP gRPC default port - for prevent duplicate expose this port that will expose also by `otel-collector` we not expose it on `4317` - `4320` could use by the app through otlptracegrpc + - "4321:4318" # OTLP Http default port - for prevent duplicate expose this port that will expose also by `otel-collector` we not expose it on `4318` - `4321` could use by the app through otlptracehttp networks: - ecommerce zipkin: image: openzipkin/zipkin:latest pull_policy: if_not_present - restart: on-failure + restart: unless-stopped container_name: zipkin ports: - "9411:9411" networks: - ecommerce -# otel-collector: -# image: otel/opentelemetry-collector-contrib-dev:latest -# pull_policy: if_not_present -# command: ["--config=/etc/otel-collector-config.yaml", ""] -# volumes: -# - ./otel-collector-config.yaml:/etc/otel-collector-config.yaml -# ports: -# - "1888:1888" # pprof extension -# - "8888:8888" # Prometheus metrics exposed by the collector -# - "8889:8889" # Prometheus exporter metrics -# - "13133:13133" # health_check extension -# - "4317:4317" # OTLP gRPC receiver -# - "55679:55679" # zpages extension -# depends_on: -# - jaeger -# - zipkin -# networks: -# - ecommerce - # https://developers.eventstore.com/server/v21.10/installation.html#insecure-single-node # https://hub.docker.com/r/eventstore/eventstore/tags # https://stackoverflow.com/questions/65272764/ports-are-not-available-listen-tcp-0-0-0-0-50070-bind-an-attempt-was-made-to @@ -209,7 +208,7 @@ services: image: eventstore/eventstore:latest pull_policy: if_not_present container_name: eventstore - restart: on-failure + restart: unless-stopped environment: - EVENTSTORE_CLUSTER_SIZE=1 - EVENTSTORE_RUN_PROJECTIONS=All @@ -233,9 +232,44 @@ services: networks: - ecommerce + # containers monitoring + cadvisor: + image: gcr.io/cadvisor/cadvisor:latest + restart: unless-stopped + ports: + - "9091:8080" + # network_mode: host + volumes: + - /:/rootfs:ro + - /var/run:/var/run:ro + - /sys:/sys:ro + - /var/lib/docker/:/var/lib/docker:ro + - /dev/disk/:/dev/disk:ro + devices: + - /dev/kmsg + networks: + - ecommerce + +# # https://stackoverflow.com/questions/67791781/how-to-configure-apm-server-to-docker-compose-file +# # https://www.elastic.co/guide/en/apm/guide/current/open-telemetry.html +# apm-server: +# image: docker.elastic.co/apm/apm-server:latest +# cap_add: ["CHOWN", "DAC_OVERRIDE", "SETGID", "SETUID"] +# cap_drop: ["ALL"] +# ports: +# - 8200:8200 +# command: > +# apm-server -e +# -E apm-server.rum.enabled=true +# -E setup.kibana.host=kibana:5601 +# -E setup.template.settings.index.number_of_replicas=0 +# -E apm-server.kibana.enabled=true +# -E apm-server.kibana.host=kibana:5601 +# -E output.elasticsearch.hosts=["elasticsearch:9200"] + # elasticsearch: # container_name: elastic_search - # restart: on-failure + # restart: unless-stopped # image: elasticsearch:8.5.2 # environment: # - discovery.type=single-node @@ -258,9 +292,9 @@ services: # kibana: # image: kibana:8.5.2 # container_name: kibana - # restart: on-failure + # restart: unless-stopped # environment: - # - ELASTICSEARCH_HOSTS=http://elastic_search:9200 + # - ELASTICSEARCH_HOSTS=http://elastic_search:${ELASTIC_PORT:-9200} # ports: # - ${KIBANA_HOST_PORT:-5601}:${KIBANA_PORT:-5601} # networks: diff --git a/deployments/docker-compose/monitoring/grafana.yaml b/deployments/docker-compose/monitoring/grafana.yaml new file mode 100644 index 00000000..47f0245a --- /dev/null +++ b/deployments/docker-compose/monitoring/grafana.yaml @@ -0,0 +1,16 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + type: prometheus + url: http://prometheus:9090 + isDefault: true + access: proxy + editable: true + + # Jaeger UI port + - name: Jaeger + type: jaeger + url: http://jaeger:16686 + access: proxy + editable: true diff --git a/deployments/docker-compose/monitoring/prometheus.yml b/deployments/docker-compose/monitoring/prometheus.yml index 7374ee79..d63262dd 100644 --- a/deployments/docker-compose/monitoring/prometheus.yml +++ b/deployments/docker-compose/monitoring/prometheus.yml @@ -1,16 +1,65 @@ +# prometheus dashboard: http://localhost:9090 +# scrap metrics our app(host.docker.internal:7000/metrics) and default internal metrics in prometheus(localhost:9090/metrics) and internal metrics in grafana(localhost:3000/metrics) + global: - scrape_interval: 10s - evaluation_interval: 10s + scrape_interval: 5s + evaluation_interval: 5s scrape_configs: - - job_name: 'prometheus' + # http://localhost:9090/metrics + - job_name: "prometheus" + metrics_path: "/metrics" + static_configs: + - targets: ["localhost:9090"] + + # http://localhost:3000/metrics + # localhost doesn't work here because inner prometheus container localhost will infer to localhost inner the container which is different with system localhost. for access to actual system localhost we should use `host.docker.internal` + # instead of `localhost` to access node_exporter container inner prometheus container we can use our container network name to access this container because they are in same docker-compose and same default network + - job_name: grafana + static_configs: + - targets: [ "grafana:3000" ] + + # http://localhost:9100/metrics + # localhost doesn't work here because inner prometheus container localhost will infer to localhost inner the container which is different with system localhost. for access to actual system localhost we should use `host.docker.internal` + # instead of `localhost` to access node_exporter container inner prometheus container we can use our container network name to access this container because they are in same docker-compose and same default network + # node_exporter will use for gathering metrics on the system level with its own /metrics endpoint like cpu, ram, ... + - job_name: node + scrape_interval: 1s + static_configs: + - targets: [ 'node_exporter:9100' ] + + # http://localhost:7000/metrics + # localhost doesn't work here because inner prometheus container localhost will infer to localhost inner the container which is different with system localhost. for access to actual system localhost we should use `host.docker.internal` + # instead of `localhost` to access node_exporter container inner prometheus container we can use our container network name to access this container because they are in same docker-compose and same default network + - job_name: product_write_service + scrape_interval: 1s + static_configs: + - targets: [ "host.docker.internal:7000" ] + + # http://localhost:7001/metrics + # localhost doesn't work here because inner prometheus container localhost will infer to localhost inner the container which is different with system localhost. for access to actual system localhost we should use `host.docker.internal` + # instead of `localhost` to access node_exporter container inner prometheus container we can use our container network name to access this container because they are in same docker-compose and same default network + - job_name: product_read_service + scrape_interval: 1s + static_configs: + - targets: [ "host.docker.internal:7001" ] + + # http://localhost:8000/metrics + # localhost doesn't work here because inner prometheus container localhost will infer to localhost inner the container which is different with system localhost. for access to actual system localhost we should use `host.docker.internal` + # instead of `localhost` to access node_exporter container inner prometheus container we can use our container network name to access this container because they are in same docker-compose and same default network + - job_name: order_service + scrape_interval: 1s static_configs: - - targets: [ 'localhost:9090' ] + - targets: [ "host.docker.internal:8000" ] - - job_name: 'product_write_service' + # Example job for cadvisor + - job_name: 'cadvisor' static_configs: - - targets: [ 'host.docker.internal:8002' ] + - targets: ['cadvisor:8080'] - - job_name: 'product_read_service' + # OpenTelemetry collector + - job_name: 'otel-collector' + scrape_interval: 10s static_configs: - - targets: [ 'host.docker.internal:8003' ] + - targets: ['otel-collector:8889'] + - targets: ['otel-collector:8888'] diff --git a/deployments/docker-compose/otel-collector-config.yaml b/deployments/docker-compose/otel-collector-config.yaml index b46e0393..63315cfc 100644 --- a/deployments/docker-compose/otel-collector-config.yaml +++ b/deployments/docker-compose/otel-collector-config.yaml @@ -24,6 +24,21 @@ exporters: endpoints: - "http://elastic_search:9200" +# #https://www.elastic.co/guide/en/apm/guide/current/open-telemetry-direct.html#open-telemetry-proxy-apm +# otlp/elastic: +# # Elastic APM server https endpoint without the "https://" prefix +# endpoint: "http://elastic-apm-server:8200" +# headers: +# # Elastic APM Server secret token +# Authorization: "Bearer ${ELASTIC_APM_SECRET_TOKEN}" + +# # https://uptrace:dev/opentelemetry/prometheus-metrics:html#prometheus-receiver +# otlp/uptrace: +# endpoint: otlp.uptrace.dev:4317 +# headers: +# # Copy your project DSN here +# uptrace-dsn: 'https://@uptrace.dev/ + processors: batch: @@ -40,12 +55,12 @@ service: traces: receivers: [otlp] processors: [batch] - exporters: [logging, zipkin, jaeger] + exporters: [logging, zipkin, jaeger] # otlp/elastic metrics: receivers: [otlp] processors: [batch] - exporters: [logging, prometheus] + exporters: [logging, prometheus] # otlp/uptrace, otlp/elastic logs: receivers: [otlp] processors: [batch] - exporters: [logging, elasticsearch] + exporters: [logging, elasticsearch] # otlp/elastic diff --git a/deployments/docker-compose/otelcollector/otelcol-config-extras.yml b/deployments/docker-compose/otelcollector/otelcol-config-extras.yml new file mode 100644 index 00000000..f557025e --- /dev/null +++ b/deployments/docker-compose/otelcollector/otelcol-config-extras.yml @@ -0,0 +1,4 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 +# extra settings to be merged into OpenTelemetry Collector configuration +# do not delete this file diff --git a/deployments/docker-compose/otelcollector/otelcol-config.yml b/deployments/docker-compose/otelcollector/otelcol-config.yml new file mode 100644 index 00000000..c16683d7 --- /dev/null +++ b/deployments/docker-compose/otelcollector/otelcol-config.yml @@ -0,0 +1,53 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +# Ref: https://github.com/open-telemetry/opentelemetry-demo/blob/main/src/otelcollector/otelcol-observability.yml +# https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/examples/demo/otel-collector-config.yaml + +receivers: + otlp: + protocols: + grpc: + http: + cors: + allowed_origins: + - "http://*" + - "https://*" + +exporters: + logging: + +processors: + batch: + transform: + metric_statements: + - context: metric + statements: + # FIXME: remove this when this is issue is resolved: https://github.com/open-telemetry/opentelemetry-java/issues/4834 + - set(description, "") where name == "queueSize" + # FIXME: remove this when the following 2 issues are resolved + # Java: https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/9478 + # Go: https://github.com/open-telemetry/opentelemetry-go-contrib/issues/4301 + - set(description, "") where name == "rpc.server.duration" + +connectors: + spanmetrics: + +extensions: + health_check: + pprof: + endpoint: :1888 + zpages: + endpoint: :55679 + +service: + extensions: [pprof, zpages, health_check] + pipelines: + traces: + receivers: [otlp] + processors: [batch] + exporters: [logging, zipkin, otlp] + metrics: + receivers: [otlp] + processors: [batch] + exporters: [logging, prometheus] \ No newline at end of file diff --git a/deployments/docker-compose/otelcollector/otelcol-observability.yml b/deployments/docker-compose/otelcollector/otelcol-observability.yml new file mode 100644 index 00000000..32f0b51e --- /dev/null +++ b/deployments/docker-compose/otelcollector/otelcol-observability.yml @@ -0,0 +1,49 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + + +exporters: + otlp: + endpoint: "jaeger:4317" + tls: + insecure: true + prometheus: + endpoint: "otelcol:9464" + resource_to_telemetry_conversion: + enabled: true + enable_open_metrics: true + + # #https://www.elastic.co/guide/en/apm/guide/current/open-telemetry-direct.html#open-telemetry-proxy-apm + # otlp/elastic: + # # Elastic APM server https endpoint without the "https://" prefix + # endpoint: "http://elastic-apm-server:8200" + # headers: + # # Elastic APM Server secret token + # Authorization: "Bearer ${ELASTIC_APM_SECRET_TOKEN}" + + # # https://uptrace:dev/opentelemetry/prometheus-metrics:html#prometheus-receiver + # otlp/uptrace: + # endpoint: otlp.uptrace.dev:4317 + # headers: + # # Copy your project DSN here + # uptrace-dsn: 'https://@uptrace.dev/ + + + logging: + + zipkin: + endpoint: "http://zipkin-all-in-one:9411/api/v2/spans" + format: proto + + otlp: + endpoint: "jaeger-all-in-one:4317" + tls: + insecure: true + +service: + pipelines: + traces: + exporters: [otlp, logging, spanmetrics] + metrics: + exporters: [prometheus, logging] + diff --git a/internal/pkg/.env b/internal/pkg/.env new file mode 100644 index 00000000..e69de29b diff --git a/internal/pkg/bun/postgres/bun_postgres.go b/internal/pkg/bun/postgres/bun_postgres.go index 81d26438..8996a85c 100644 --- a/internal/pkg/bun/postgres/bun_postgres.go +++ b/internal/pkg/bun/postgres/bun_postgres.go @@ -37,7 +37,7 @@ func NewBunDB(cfg *bun2.BunConfig) (*bun.DB, error) { //pgconn := pgdriver.NewConnector( // pgdriver.WithNetwork("tcp"), // pgdriver.WithAddr("localhost:5437"), - // pgdriver.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}), + // pgdriver.WithTLSConfig(&tls.config{InsecureSkipVerify: true}), // pgdriver.WithUser("test"), // pgdriver.WithPassword("test"), // pgdriver.WithDatabase("test"), diff --git a/internal/pkg/config.development.json b/internal/pkg/config.development.json new file mode 100644 index 00000000..eeff3f84 --- /dev/null +++ b/internal/pkg/config.development.json @@ -0,0 +1,85 @@ +{ + "appOptions": { + "serviceName": "test", + "deliveryType": "http" + }, + "grpcOptions": { + "name": "test", + "port": ":6003", + "host": "localhost", + "development": true + }, + "echoHttpOptions": { + "name": "test", + "port": ":7000", + "development": true, + "timeout": 30, + "basePath": "/api/v1", + "host": "http://localhost", + "productsPath": "products", + "debugHeaders": true, + "httpClientDebug": true, + "debugErrorsResponse": true, + "ignoreLogUrls": [ + "metrics" + ] + }, + "logOptions": { + "level": "debug", + "logType": 0, + "callerEnabled": false + }, + "gormOptions": { + "host": "localhost", + "port": 5432, + "user": "postgres", + "password": "postgres", + "dbName": "catalogs_service", + "sslMode": false + }, + "rabbitmqOptions": { + "autoStart": true, + "reconnecting": true, + "rabbitmqHostOptions": { + "userName": "guest", + "password": "guest", + "hostName": "localhost", + "port": 5672, + "httpPort": 15672 + } + }, + "tracingOptions": { + "enable": true, + "serviceName": "test", + "instrumentationName": "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test", + "id": 1, + "useStdout": false, + "alwaysOnSampler": true, + "jaegerExporterOptions": { + "otlpEndpoint": "localhost:4317" + }, + "zipkinExporterOptions": { + "url": "http://localhost:9411/api/v2/spans" + } + }, + "metricsOptions": { + "host": "localhost", + "port": ":3001", + "metricsRoutePath": "metrics", + "serviceName": "test", + "instrumentationName": "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test" + }, + "eventStoreDbOptions": { + "connectionString": "esdb://localhost:2113?tls=false" + }, + "migrationOptions": { + "host": "localhost", + "port": 5432, + "user": "postgres", + "password": "postgres", + "dbName": "catalogs_service", + "sslMode": false, + "migrationsDir": "db/migrations/goose-migrate", + "skipMigration": false + } +} diff --git a/internal/pkg/config/config_helper.go b/internal/pkg/config/config_helper.go index 9a83a632..c46e4cf7 100644 --- a/internal/pkg/config/config_helper.go +++ b/internal/pkg/config/config_helper.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "path/filepath" + "strings" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/constants" @@ -19,7 +20,10 @@ func BindConfig[T any](environments ...environemnt.Environment) (T, error) { return BindConfigKey[T]("", environments...) } -func BindConfigKey[T any](configKey string, environments ...environemnt.Environment) (T, error) { +func BindConfigKey[T any]( + configKey string, + environments ...environemnt.Environment, +) (T, error) { var configPath string environment := environemnt.Environment("") @@ -29,16 +33,25 @@ func BindConfigKey[T any](configKey string, environments ...environemnt.Environm environment = constants.Dev } + cfg := typeMapper.GenericInstanceByT[T]() + + // this should set before reading config values from json file + // https://github.com/mcuadros/go-defaults + defaults.SetDefaults(cfg) + // https://articles.wesionary.team/environment-variable-configuration-in-your-golang-project-using-viper-4e8289ef664d // when we `Set` a viper with string value, we should get it from viper with `viper.GetString`, elsewhere we get empty string // load `config path` from environment variable or viper internal registry configPathFromEnv := viper.GetString(constants.ConfigPath) + if configPathFromEnv != "" { configPath = configPathFromEnv } else { // https://stackoverflow.com/questions/31873396/is-it-possible-to-get-the-current-root-of-package-structure-as-a-string-in-golan // https://stackoverflow.com/questions/18537257/how-to-get-the-directory-of-the-currently-running-file - d, err := getConfigRootPath() + appRootPath := viper.GetString(constants.AppRootPath) + + d, err := searchForConfigFileDir(appRootPath, environment) if err != nil { return *new(T), err } @@ -46,12 +59,6 @@ func BindConfigKey[T any](configKey string, environments ...environemnt.Environm configPath = d } - cfg := typeMapper.GenericInstanceByT[T]() - - // this should set before reading config values from json file - // https://github.com/mcuadros/go-defaults - defaults.SetDefaults(cfg) - // https://github.com/spf13/viper/issues/390#issuecomment-718756752 viper.SetConfigName(fmt.Sprintf("config.%s", environment)) viper.AddConfigPath(configPath) @@ -62,6 +69,7 @@ func BindConfigKey[T any](configKey string, environments ...environemnt.Environm } if len(configKey) == 0 { + // load configs from config file to config object if err := viper.Unmarshal(cfg); err != nil { return *new(T), errors.WrapIf(err, "viper.Unmarshal") } @@ -81,23 +89,60 @@ func BindConfigKey[T any](configKey string, environments ...environemnt.Environm return cfg, nil } -func getConfigRootPath() (string, error) { - // Get the current working directory - // Getwd gives us the current working directory that we are running our app with `go run` command. in goland we can specify this working directory for the project - wd, err := os.Getwd() - if err != nil { - return "", err - } - fmt.Println(fmt.Sprintf("Current working directory is: %s", wd)) - - // Get the absolute path of the executed project directory - absCurrentDir, err := filepath.Abs(wd) - if err != nil { - return "", err +// searchForConfigFileDir searches for the first directory within the specified root directory and its subdirectories +// that contains a file named "config.%s.json" where "%s" is replaced with the provided environment string. +// It returns the path of the first directory that contains the config file or an error if no such directory is found. +// +// Parameters: +// +// rootDir: The root directory to start the search from. +// environment: The environment string to replace "%s" in the config file name. +// +// Returns: +// +// string: The path of the directory containing the config file, or an empty string if not found. +// error: An error indicating any issues encountered during the search. +func searchForConfigFileDir( + rootDir string, + environment environemnt.Environment, +) (string, error) { + var result string + + // Walk the directory tree starting from rootDir + err := filepath.Walk( + rootDir, + func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + // Check if the file is named "config.%s.json" (replace %s with the environment) + if !info.IsDir() && + strings.EqualFold( + info.Name(), + fmt.Sprintf("config.%s.json", environment), + ) || + strings.EqualFold( + info.Name(), + fmt.Sprintf("config.%s.yaml", environment), + ) || + strings.EqualFold( + info.Name(), + fmt.Sprintf("config.%s.yml", environment), + ) { + // Get the directory name containing the config file + dir := filepath.Dir(path) + result = dir + return filepath.SkipDir // Skip further traversal + } + + return nil + }, + ) + + if result != "" { + return result, nil } - // Get the path to the "config" folder within the project directory - configPath := filepath.Join(absCurrentDir, "config") - - return configPath, nil + return "", errors.WrapIf(err, "No directory with config file found") } diff --git a/internal/pkg/config/environemnt/environment.go b/internal/pkg/config/environemnt/environment.go index 651d1f1d..7a0ededf 100644 --- a/internal/pkg/config/environemnt/environment.go +++ b/internal/pkg/config/environemnt/environment.go @@ -34,7 +34,7 @@ func ConfigAppEnv(environments ...Environment) Environment { viper.AutomaticEnv() // https://articles.wesionary.team/environment-variable-configuration-in-your-golang-project-using-viper-4e8289ef664d - // load environment variables form .env files to system environment variables, it just find `.env` file in our current `executing working directory` in our app for example `catalogs_service` + // load environment variables form .env files to system environment variables, it just finds `.env` file in our current `executing working directory` in our app for example `catalogs_service` err := loadEnvFilesRecursive() if err != nil { log.Printf(".env file cannot be found, err: %v", err) @@ -101,17 +101,29 @@ func loadEnvFilesRecursive() error { } func setRootWorkingDirectoryEnvironment() { + var rootWorkingDirectory string // https://articles.wesionary.team/environment-variable-configuration-in-your-golang-project-using-viper-4e8289ef664d // when we `Set` a viper with string value, we should get it from viper with `viper.GetString`, elsewhere we get empty string // viper will get it from `os env` or a .env file pn := viper.GetString(constants.PROJECT_NAME_ENV) - if pn == "" { - log.Fatalf( - "can't find environment variable `%s` in the system environment variables or a .env file", - constants.PROJECT_NAME_ENV, - ) + if pn != "" { + rootWorkingDirectory = getRootDirectoryFromProjectName(pn) + } else { + wd, _ := os.Getwd() + dir, err := searchRootDirectory(wd) + if err != nil { + log.Fatal(err) + } + rootWorkingDirectory = dir } + absoluteRootWorkingDirectory, _ := filepath.Abs(rootWorkingDirectory) + + // when we `Set` a viper with string value, we should get it from viper with `viper.GetString`, elsewhere we get empty string + viper.Set(constants.AppRootPath, absoluteRootWorkingDirectory) +} + +func getRootDirectoryFromProjectName(pn string) string { // set root working directory of our app in the viper // https://stackoverflow.com/a/47785436/581476 wd, _ := os.Getwd() @@ -120,18 +132,36 @@ func setRootWorkingDirectoryEnvironment() { wd = filepath.Dir(wd) } - absoluteRootWorkingDirectory, _ := filepath.Abs(wd) - - // when we `Set` a viper with string value, we should get it from viper with `viper.GetString`, elsewhere we get empty string - viper.Set(constants.AppRootPath, absoluteRootWorkingDirectory) + return wd +} - configPath := viper.GetString(constants.ConfigPath) +func searchRootDirectory( + dir string, +) (string, error) { + // List files and directories in the current directory + files, err := os.ReadDir(dir) + if err != nil { + return "", errors.WrapIf(err, "Error reading directory") + } - // check for existing `CONFIG_PATH` variable in system environment variables - we can set it directly in .env file or system environments - if configPath == "" { - configPath := filepath.Join(absoluteRootWorkingDirectory, "config") + for _, file := range files { + if !file.IsDir() { + fileName := file.Name() + if strings.EqualFold( + fileName, + "go.mod", + ) { + return dir, nil + } + } + } - // when we `Set` a viper with string value, we should get it from viper with `viper.GetString`, elsewhere we get empty string - viper.Set(constants.ConfigPath, configPath) + // If no config file found in this directory, recursively search its parent + parentDir := filepath.Dir(dir) + if parentDir == dir { + // We've reached the root directory, and no go.mod file was found + return "", errors.WrapIf(err, "No go.mod file found") } + + return searchRootDirectory(parentDir) } diff --git a/internal/pkg/go.mod b/internal/pkg/go.mod index 9d147d48..2ace5837 100644 --- a/internal/pkg/go.mod +++ b/internal/pkg/go.mod @@ -16,7 +16,6 @@ require ( github.com/doug-martin/goqu/v9 v9.18.0 github.com/elastic/go-elasticsearch/v8 v8.10.0 github.com/go-playground/validator v9.31.0+incompatible - github.com/go-redis/redis v6.15.9+incompatible github.com/go-resty/resty/v2 v2.8.0 github.com/go-testfixtures/testfixtures/v3 v3.9.0 github.com/goccy/go-json v0.10.2 @@ -38,6 +37,8 @@ require ( github.com/michaelklishin/rabbit-hole v1.5.0 github.com/mitchellh/mapstructure v1.5.0 github.com/nolleh/caption_json_formatter v0.2.2 + github.com/onsi/ginkgo/v2 v2.12.1 + github.com/onsi/gomega v1.27.10 github.com/orlangure/gnomock v0.30.0 github.com/ory/dockertest/v3 v3.10.0 github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 @@ -56,15 +57,19 @@ require ( github.com/uptrace/bun v1.1.16 github.com/uptrace/bun/dialect/pgdialect v1.1.16 github.com/uptrace/bun/driver/pgdriver v1.1.16 + github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2 github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 go.mongodb.org/mongo-driver v1.12.1 go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 + go.opentelemetry.io/contrib/instrumentation/host v0.44.0 go.opentelemetry.io/contrib/propagators/ot v1.19.0 go.opentelemetry.io/otel v1.18.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 go.opentelemetry.io/otel/exporters/prometheus v0.41.0 + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 go.opentelemetry.io/otel/exporters/zipkin v1.18.0 go.opentelemetry.io/otel/metric v1.18.0 @@ -73,7 +78,7 @@ require ( go.opentelemetry.io/otel/trace v1.18.0 go.uber.org/fx v1.20.0 go.uber.org/zap v1.26.0 - google.golang.org/grpc v1.58.1 + google.golang.org/grpc v1.58.2 gorm.io/driver/postgres v1.5.2 gorm.io/gorm v1.25.4 gorm.io/plugin/opentelemetry v0.1.4 @@ -85,7 +90,7 @@ require ( github.com/ClickHouse/ch-go v0.58.2 // indirect github.com/ClickHouse/clickhouse-go/v2 v2.14.1 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/Microsoft/hcsshim v0.11.0 // indirect + github.com/Microsoft/hcsshim v0.11.1 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/andybalholm/brotli v1.0.5 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -109,11 +114,14 @@ require ( github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect @@ -160,14 +168,14 @@ require ( github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.11.1 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/shirou/gopsutil/v3 v3.23.8 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shopspring/decimal v1.3.1 // indirect - github.com/spf13/afero v1.9.5 // indirect + github.com/spf13/afero v1.10.0 // indirect github.com/spf13/cast v1.5.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect @@ -190,6 +198,7 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/atomic v1.11.0 // indirect diff --git a/internal/pkg/go.sum b/internal/pkg/go.sum index 7cfca3c0..0b331477 100644 --- a/internal/pkg/go.sum +++ b/internal/pkg/go.sum @@ -68,8 +68,8 @@ github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA4 github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.11.0 h1:7EFNIY4igHEXUdj1zXgAyU3fLc7QfOKHbkldRVTBdiM= -github.com/Microsoft/hcsshim v0.11.0/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= +github.com/Microsoft/hcsshim v0.11.1 h1:hJ3s7GbWlGK4YVV92sO88BQSyF4ZLVy7/awqOlPxFbA= +github.com/Microsoft/hcsshim v0.11.1/go.mod h1:nFJmaO4Zr5Y7eADdFOpYswDDlNVbvcIJJNJLECr5JQg= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4= @@ -203,14 +203,14 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator v9.31.0+incompatible h1:UA72EPEogEnq76ehGdEDp4Mit+3FDh548oRqwVgNsHA= github.com/go-playground/validator v9.31.0+incompatible/go.mod h1:yrEkQXlcI+PugkyDjY2bRrL/UBU4f3rvrgkN3V8JEig= -github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= -github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-resty/resty/v2 v2.8.0 h1:J29d0JFWwSWrDCysnOK/YjsPMLQTx0TvgJEHVGvf2L8= github.com/go-resty/resty/v2 v2.8.0/go.mod h1:UCui0cMHekLrSntoMyofdSTaPpinlRHFtPpizuyDW2w= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-testfixtures/testfixtures/v3 v3.9.0 h1:938g5V+GWLVejm3Hc+nWCuEXRlcglZDDlN/t1gWzcSY= github.com/go-testfixtures/testfixtures/v3 v3.9.0/go.mod h1:cdsKD2ApFBjdog9jRsz6EJqF+LClq/hrwE9K/1Dzo4s= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= @@ -297,6 +297,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 h1:gpptm606MZYGaMHMsB4Srmb6EbW/IVHnt04rcMXnkBQ= +github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -491,6 +493,8 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.12.1 h1:uHNEO1RP2SpuZApSkel9nEh1/Mu+hmQe7Q+Pepg5OYA= +github.com/onsi/ginkgo/v2 v2.12.1/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= @@ -542,8 +546,8 @@ github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUo github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rabbitmq/amqp091-go v1.8.1 h1:RejT1SBUim5doqcL6s7iN6SBmsQqyTgXb1xMlH0h1hA= github.com/rabbitmq/amqp091-go v1.8.1/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv/f+6luSD3pc= github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fOGwTfezUiUJMaIcaho= @@ -591,8 +595,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= +github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= @@ -646,6 +650,8 @@ github.com/uptrace/bun/dialect/pgdialect v1.1.16 h1:eUPZ+YCJ69BA+W1X1ZmpOJSkv1oY github.com/uptrace/bun/dialect/pgdialect v1.1.16/go.mod h1:KQjfx/r6JM0OXfbv0rFrxAbdkPD7idK8VitnjIV9fZI= github.com/uptrace/bun/driver/pgdriver v1.1.16 h1:b/NiSXk6Ldw7KLfMLbOqIkm4odHd7QiNOCPLqPFJjK4= github.com/uptrace/bun/driver/pgdriver v1.1.16/go.mod h1:Rmfbc+7lx1z/umjMyAxkOHK81LgnGj71XC5YpA6k1vU= +github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2 h1:s3quVevwQlgEMCkvscS/VHo92amtyMzRfcuOZqfevrM= +github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2/go.mod h1:IJLBT7ItgUACTEoq6BEw/9HwHWL4BiPirYgKhZS83Lg= github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 h1:CNznWHkrbA6o1q2H/BsH4tIHf4zbKNtndeoV+AH8z0U= github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2/go.mod h1:7YSrHCmYPHIXjTWnKSU7EGT0TFEcm3WwSeQquwCGg38= github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 h1:uyrW06oJi4iWvhjPLVfk4qrSP2Zm0AMozKKDmp6i4pE= @@ -708,18 +714,26 @@ go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/ot go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0/go.mod h1:JH6FxBlkXo/cYoU/m65W5dOQ6sqPL+jHtSJaSE7/+XQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 h1:b8xjZxHbLrXAum4SxJd1Rlm7Y/fKaB+6ACI7/e5EfSA= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0/go.mod h1:1ei0a32xOGkFoySu7y1DAHfcuIhC0pNZpvY2huXuMy4= +go.opentelemetry.io/contrib/instrumentation/host v0.44.0 h1:SNqDjPpQmwFYvDipyJJxDbU5zKNWiYSMii864ubzIuQ= +go.opentelemetry.io/contrib/instrumentation/host v0.44.0/go.mod h1:bZcqg3yy0riQLNkx8dJWV4J3tbfL+6LQ5lIbI+vmarE= go.opentelemetry.io/contrib/propagators/b3 v1.19.0 h1:ulz44cpm6V5oAeg5Aw9HyqGFMS6XM7untlMEhD7YzzA= go.opentelemetry.io/contrib/propagators/b3 v1.19.0/go.mod h1:OzCmE2IVS+asTI+odXQstRGVfXQ4bXv9nMBRK0nNyqQ= go.opentelemetry.io/contrib/propagators/ot v1.19.0 h1:vODRLMlKN4ApM8ri0UDk8nnEeISuwxpf67sE7PmOHhE= go.opentelemetry.io/contrib/propagators/ot v1.19.0/go.mod h1:S2Uc7th2ZmLiHu0lrCmDCgTQ/y5Nbbis+TNjR1jjm4Q= go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 h1:k0k7hFNDd8K4iOMJXj7s8sHaC4mhTlAeppRmZXLgZ6k= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 h1:HgbDTD8pioFdY3NRc/YCvsWjqQPtweGyXxa32LgnTOw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0/go.mod h1:tmvt/yK5Es5d6lHYWerLSOna8lCEfrBVX/a9M0ggqss= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 h1:IAtl+7gua134xcV3NieDhJHjjOVeJhXAnYf/0hswjUY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0/go.mod h1:w+pXobnBzh95MNIkeIuAKcHe/Uu/CX2PKIvBP6ipKRA= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32ay7mJG2leczfREEhoW3VfSZIvHaB+gvVo1o8DQ8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4= go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 h1:XzjGkawtAXs20Y+s6k1GNDMBsMDOV28TOT8cxmE42qM= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0/go.mod h1:HAomEgjcKZk3VJ+HHdHLnhZXeGqdzPxxNTdKYRopUXY= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes= go.opentelemetry.io/otel/exporters/zipkin v1.18.0 h1:ZqrHgvega5NIiScTiVrtpZSpEmjUdwzkhuuCEIMAp+s= @@ -1143,8 +1157,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I= +google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/internal/pkg/gorm_postgres/db.go b/internal/pkg/gorm_postgres/db.go index 3b86314a..ab5b5328 100644 --- a/internal/pkg/gorm_postgres/db.go +++ b/internal/pkg/gorm_postgres/db.go @@ -11,6 +11,7 @@ import ( "github.com/uptrace/bun/driver/pgdriver" gormPostgres "gorm.io/driver/postgres" "gorm.io/gorm" + "gorm.io/plugin/opentelemetry/tracing" ) func NewGorm(cfg *GormOptions) (*gorm.DB, error) { @@ -41,6 +42,11 @@ func NewGorm(cfg *GormOptions) (*gorm.DB, error) { return nil, err } + // add tracing to gorm + if cfg.EnableTracing { + err = gormDb.Use(tracing.NewPlugin()) + } + return gormDb, nil } diff --git a/internal/pkg/gorm_postgres/gorm_options.go b/internal/pkg/gorm_postgres/gorm_options.go index 7b78b78b..593d677e 100644 --- a/internal/pkg/gorm_postgres/gorm_options.go +++ b/internal/pkg/gorm_postgres/gorm_options.go @@ -13,12 +13,13 @@ import ( var optionName = strcase.ToLowerCamel(typeMapper.GetTypeNameByT[GormOptions]()) type GormOptions struct { - Host string `mapstructure:"host"` - Port int `mapstructure:"port"` - User string `mapstructure:"user"` - DBName string `mapstructure:"dbName"` - SSLMode bool `mapstructure:"sslMode"` - Password string `mapstructure:"password"` + Host string `mapstructure:"host"` + Port int `mapstructure:"port"` + User string `mapstructure:"user"` + DBName string `mapstructure:"dbName"` + SSLMode bool `mapstructure:"sslMode"` + Password string `mapstructure:"password"` + EnableTracing bool `mapstructure:"enableTracing" default:"true"` } func (h *GormOptions) Dns() string { diff --git a/internal/pkg/gorm_postgres/gorm_postgres_fx.go b/internal/pkg/gorm_postgres/gorm_postgres_fx.go index 742e68a5..c61a4038 100644 --- a/internal/pkg/gorm_postgres/gorm_postgres_fx.go +++ b/internal/pkg/gorm_postgres/gorm_postgres_fx.go @@ -3,11 +3,9 @@ package gormPostgres import ( "fmt" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health/contracts" "go.uber.org/fx" - "gorm.io/gorm" - "gorm.io/plugin/opentelemetry/tracing" ) // Module provided to fxlog @@ -20,14 +18,8 @@ var Module = fx.Module( NewSQLDB, fx.Annotate( NewGormHealthChecker, - fx.As(new(health.Health)), + fx.As(new(contracts.Health)), fx.ResultTags(fmt.Sprintf(`group:"%s"`, "healths")), ), ), - fx.Invoke(EnableTracing), ) - -func EnableTracing(gormDb *gorm.DB) error { - // add tracing to gorm - return gormDb.Use(tracing.NewPlugin()) -} diff --git a/internal/pkg/gorm_postgres/health.go b/internal/pkg/gorm_postgres/health.go index 16838f76..4d1f177d 100644 --- a/internal/pkg/gorm_postgres/health.go +++ b/internal/pkg/gorm_postgres/health.go @@ -4,14 +4,14 @@ import ( "context" "database/sql" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health/contracts" ) type gormHealthChecker struct { client *sql.DB } -func NewGormHealthChecker(client *sql.DB) health.Health { +func NewGormHealthChecker(client *sql.DB) contracts.Health { return &gormHealthChecker{client} } diff --git a/internal/pkg/grpc/server.go b/internal/pkg/grpc/server.go index 6b9296f5..6ab48229 100644 --- a/internal/pkg/grpc/server.go +++ b/internal/pkg/grpc/server.go @@ -51,12 +51,14 @@ func NewGrpcServer( meter metric.Meter, ) GrpcServer { unaryServerInterceptors := []googleGrpc.UnaryServerInterceptor{ + // https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/example_interceptor_test.go otelgrpc.UnaryServerInterceptor(), grpcError.UnaryServerInterceptor(), grpcCtxTags.UnaryServerInterceptor(), grpcRecovery.UnaryServerInterceptor(), } streamServerInterceptors := []googleGrpc.StreamServerInterceptor{ + // https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/example_interceptor_test.go otelgrpc.StreamServerInterceptor(), grpcError.StreamServerInterceptor(), } @@ -66,6 +68,7 @@ func NewGrpcServer( unaryServerInterceptors, otelMetrics.UnaryServerInterceptor(meter, config.Name), ) + streamServerInterceptors = append( streamServerInterceptors, otelMetrics.StreamServerInterceptor(meter, config.Name), @@ -88,10 +91,12 @@ func NewGrpcServer( unaryServerInterceptors..., )), ) - healthServer := health.NewServer() grpc_health_v1.RegisterHealthServer(s, healthServer) - healthServer.SetServingStatus(config.Name, grpc_health_v1.HealthCheckResponse_SERVING) + healthServer.SetServingStatus( + config.Name, + grpc_health_v1.HealthCheckResponse_SERVING, + ) return &grpcServer{ server: s, @@ -130,7 +135,10 @@ func (s *grpcServer) RunGrpcServer( if err != nil { s.log.Error( - fmt.Sprintf("[grpcServer_RunGrpcServer.Serve] grpc server serve error: %+v", err), + fmt.Sprintf( + "[grpcServer_RunGrpcServer.Serve] grpc server serve error: %+v", + err, + ), ) } diff --git a/internal/pkg/health/check.go b/internal/pkg/health/contracts/check.go similarity index 89% rename from internal/pkg/health/check.go rename to internal/pkg/health/contracts/check.go index e7db842a..eeb6e081 100644 --- a/internal/pkg/health/check.go +++ b/internal/pkg/health/contracts/check.go @@ -1,4 +1,4 @@ -package health +package contracts type Check map[string]Status @@ -8,5 +8,6 @@ func (check Check) AllUp() bool { return false } } + return true } diff --git a/internal/pkg/health/health.go b/internal/pkg/health/contracts/health.go similarity index 54% rename from internal/pkg/health/health.go rename to internal/pkg/health/contracts/health.go index 2545fca1..d35731a2 100644 --- a/internal/pkg/health/health.go +++ b/internal/pkg/health/contracts/health.go @@ -1,4 +1,4 @@ -package health +package contracts import "context" @@ -6,3 +6,7 @@ type Health interface { CheckHealth(ctx context.Context) error GetHealthName() string } + +type HealthService interface { + CheckHealth(ctx context.Context) Check +} diff --git a/internal/pkg/health/health_params.go b/internal/pkg/health/contracts/health_params.go similarity index 85% rename from internal/pkg/health/health_params.go rename to internal/pkg/health/contracts/health_params.go index 0141da67..a404c377 100644 --- a/internal/pkg/health/health_params.go +++ b/internal/pkg/health/contracts/health_params.go @@ -1,4 +1,4 @@ -package health +package contracts import ( "go.uber.org/fx" diff --git a/internal/pkg/health/status.go b/internal/pkg/health/contracts/status.go similarity index 94% rename from internal/pkg/health/status.go rename to internal/pkg/health/contracts/status.go index d808dfaa..127ae9a7 100644 --- a/internal/pkg/health/status.go +++ b/internal/pkg/health/contracts/status.go @@ -1,4 +1,4 @@ -package health +package contracts const ( StatusUp = "up" diff --git a/internal/pkg/health/health_endpoint.go b/internal/pkg/health/health_endpoint.go index 94d6b785..75a10fcd 100644 --- a/internal/pkg/health/health_endpoint.go +++ b/internal/pkg/health/health_endpoint.go @@ -3,32 +3,33 @@ package health import ( "net/http" - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + contracts2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" "github.com/labstack/echo/v4" ) type HealthCheckEndpoint struct { - service HealthService - echoServer customEcho.EchoHttpServer + service contracts2.HealthService + echoServer contracts.EchoHttpServer } func NewHealthCheckEndpoint( - service HealthService, - server customEcho.EchoHttpServer, + service contracts2.HealthService, + server contracts.EchoHttpServer, ) *HealthCheckEndpoint { return &HealthCheckEndpoint{service: service, echoServer: server} } func (s *HealthCheckEndpoint) RegisterEndpoints() { - s.echoServer.GetEchoInstance().Group("").GET("health", s.CheckHealth) + s.echoServer.GetEchoInstance().GET("health", s.checkHealth) } -func (s *HealthCheckEndpoint) CheckHealth(c echo.Context) error { +func (s *HealthCheckEndpoint) checkHealth(c echo.Context) error { check := s.service.CheckHealth(c.Request().Context()) if !check.AllUp() { return c.JSON(http.StatusServiceUnavailable, check) } - err := c.JSON(http.StatusOK, check) - return err + + return c.JSON(http.StatusOK, check) } diff --git a/internal/pkg/health/health_fx.go b/internal/pkg/health/health_fx.go index 2b86b93d..54ddd25c 100644 --- a/internal/pkg/health/health_fx.go +++ b/internal/pkg/health/health_fx.go @@ -4,7 +4,7 @@ import ( "go.uber.org/fx" ) -var Module = fx.Options( +var Module = fx.Options( //nolint:gochecknoglobals fx.Provide( NewHealthService, NewHealthCheckEndpoint, diff --git a/internal/pkg/health/service.go b/internal/pkg/health/service.go index 98a568a5..8cd48179 100644 --- a/internal/pkg/health/service.go +++ b/internal/pkg/health/service.go @@ -2,29 +2,29 @@ package health import ( "context" -) -type HealthService interface { - CheckHealth(ctx context.Context) Check -} + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health/contracts" +) type healthService struct { - healthParams HealthParams + healthParams contracts.HealthParams } func NewHealthService( - healthParams HealthParams, -) HealthService { + healthParams contracts.HealthParams, +) contracts.HealthService { return &healthService{ healthParams: healthParams, } } -func (service *healthService) CheckHealth(ctx context.Context) Check { - checks := make(Check) +func (service *healthService) CheckHealth(ctx context.Context) contracts.Check { + checks := make(contracts.Check) for _, health := range service.healthParams.Healths { - checks[health.GetHealthName()] = NewStatus(health.CheckHealth(ctx)) + checks[health.GetHealthName()] = contracts.NewStatus( + health.CheckHealth(ctx), + ) } return checks diff --git a/internal/pkg/health/unhealthy.go b/internal/pkg/health/unhealthy.go index 75852493..499d703a 100644 --- a/internal/pkg/health/unhealthy.go +++ b/internal/pkg/health/unhealthy.go @@ -1,16 +1,22 @@ package health -import "context" +import ( + "context" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health/contracts" +) + +type UnhealthyHealthService struct{} func NewUnhealthyHealthService() UnhealthyHealthService { return UnhealthyHealthService{} } -type UnhealthyHealthService struct{} - -func (service UnhealthyHealthService) CheckHealth(context.Context) Check { - return Check{ - "postgres": Status{Status: StatusDown}, - "redis": Status{Status: StatusDown}, +func (service UnhealthyHealthService) CheckHealth( + context.Context, +) contracts.Check { + return contracts.Check{ + "postgres": contracts.Status{Status: contracts.StatusDown}, + "redis": contracts.Status{Status: contracts.StatusDown}, } } diff --git a/internal/pkg/http/custom_echo/contracts/echoserver.go b/internal/pkg/http/custom_echo/contracts/echoserver.go new file mode 100644 index 00000000..a53f95ef --- /dev/null +++ b/internal/pkg/http/custom_echo/contracts/echoserver.go @@ -0,0 +1,23 @@ +package contracts + +import ( + "context" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + + "github.com/labstack/echo/v4" +) + +type EchoHttpServer interface { + RunHttpServer(configEcho ...func(echo *echo.Echo)) error + GracefulShutdown(ctx context.Context) error + ApplyVersioningFromHeader() + GetEchoInstance() *echo.Echo + Logger() logger.Logger + Cfg() *config.EchoHttpOptions + SetupDefaultMiddlewares() + RouteBuilder() *RouteBuilder + AddMiddlewares(middlewares ...echo.MiddlewareFunc) + ConfigGroup(groupName string, groupFunc func(group *echo.Group)) +} diff --git a/internal/pkg/http/custom_echo/route_builder.go b/internal/pkg/http/custom_echo/contracts/route_builder.go similarity index 96% rename from internal/pkg/http/custom_echo/route_builder.go rename to internal/pkg/http/custom_echo/contracts/route_builder.go index ba9cc52a..2bfb739a 100644 --- a/internal/pkg/http/custom_echo/route_builder.go +++ b/internal/pkg/http/custom_echo/contracts/route_builder.go @@ -1,4 +1,4 @@ -package customEcho +package contracts import "github.com/labstack/echo/v4" diff --git a/internal/pkg/http/custom_echo/custom_echo_fx.go b/internal/pkg/http/custom_echo/custom_echo_fx.go index c86ccafc..a73fa406 100644 --- a/internal/pkg/http/custom_echo/custom_echo_fx.go +++ b/internal/pkg/http/custom_echo/custom_echo_fx.go @@ -6,6 +6,7 @@ import ( "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "go.uber.org/fx" @@ -42,7 +43,11 @@ var ( ) // we don't want to register any dependencies here, its func body should execute always even we don't request for that, so we should use `invoke` -func registerHooks(lc fx.Lifecycle, echoServer EchoHttpServer, logger logger.Logger) { +func registerHooks( + lc fx.Lifecycle, + echoServer contracts.EchoHttpServer, + logger logger.Logger, +) { lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { // https://github.com/uber-go/fx/blob/v1.20.0/app.go#L573 @@ -52,7 +57,10 @@ func registerHooks(lc fx.Lifecycle, echoServer EchoHttpServer, logger logger.Log go func() { // https://medium.com/@mokiat/proper-http-shutdown-in-go-bd3bfaade0f2 // When Shutdown is called, Serve, ListenAndServe, and ListenAndServeTLS immediately return ErrServerClosed. Make sure the program doesn’t exit and waits instead for Shutdown to return. - if err := echoServer.RunHttpServer(); !errors.Is(err, http.ErrServerClosed) { + if err := echoServer.RunHttpServer(); !errors.Is( + err, + http.ErrServerClosed, + ) { // do a fatal for going to OnStop process logger.Fatalf( "(EchoHttpServer.RunHttpServer) error in running server: {%v}", @@ -75,7 +83,8 @@ func registerHooks(lc fx.Lifecycle, echoServer EchoHttpServer, logger logger.Log // https://medium.com/@mokiat/proper-http-shutdown-in-go-bd3bfaade0f2 // When Shutdown is called, Serve, ListenAndServe, and ListenAndServeTLS immediately return ErrServerClosed. Make sure the program doesn’t exit and waits instead for Shutdown to return. if err := echoServer.GracefulShutdown(ctx); err != nil { - echoServer.Logger().Errorf("error shutting down echo server: %v", err) + echoServer.Logger(). + Errorf("error shutting down echo server: %v", err) } else { echoServer.Logger().Info("echo server shutdown gracefully") } diff --git a/internal/pkg/http/custom_echo/echo_server.go b/internal/pkg/http/custom_echo/echo_server.go index fe8349e5..995ad40a 100644 --- a/internal/pkg/http/custom_echo/echo_server.go +++ b/internal/pkg/http/custom_echo/echo_server.go @@ -7,6 +7,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/constants" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" customHadnlers "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/hadnlers" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/middlewares/log" otelMetrics "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/middlewares/otel_metrics" @@ -23,27 +24,14 @@ type echoHttpServer struct { config *config.EchoHttpOptions log logger.Logger meter metric.Meter - routeBuilder *RouteBuilder -} - -type EchoHttpServer interface { - RunHttpServer(configEcho ...func(echo *echo.Echo)) error - GracefulShutdown(ctx context.Context) error - ApplyVersioningFromHeader() - GetEchoInstance() *echo.Echo - Logger() logger.Logger - Cfg() *config.EchoHttpOptions - SetupDefaultMiddlewares() - RouteBuilder() *RouteBuilder - AddMiddlewares(middlewares ...echo.MiddlewareFunc) - ConfigGroup(groupName string, groupFunc func(group *echo.Group)) + routeBuilder *contracts.RouteBuilder } func NewEchoHttpServer( config *config.EchoHttpOptions, logger logger.Logger, meter metric.Meter, -) EchoHttpServer { +) contracts.EchoHttpServer { e := echo.New() e.HideBanner = false @@ -52,7 +40,7 @@ func NewEchoHttpServer( config: config, log: logger, meter: meter, - routeBuilder: NewRouteBuilder(e), + routeBuilder: contracts.NewRouteBuilder(e), } } @@ -82,11 +70,14 @@ func (s *echoHttpServer) Cfg() *config.EchoHttpOptions { return s.config } -func (s *echoHttpServer) RouteBuilder() *RouteBuilder { +func (s *echoHttpServer) RouteBuilder() *contracts.RouteBuilder { return s.routeBuilder } -func (s *echoHttpServer) ConfigGroup(groupName string, groupFunc func(group *echo.Group)) { +func (s *echoHttpServer) ConfigGroup( + groupName string, + groupFunc func(group *echo.Group), +) { groupFunc(s.echo.Group(groupName)) } @@ -115,38 +106,63 @@ func (s *echoHttpServer) SetupDefaultMiddlewares() { customHadnlers.ProblemHandlerFunc(err, c, s.log) } + skipper := func(c echo.Context) bool { + return strings.Contains(c.Request().URL.Path, "swagger") || + strings.Contains(c.Request().URL.Path, "metrics") || + strings.Contains(c.Request().URL.Path, "health") || + strings.Contains(c.Request().URL.Path, "favicon.ico") + } + // log errors and information - s.echo.Use(log.EchoLogger(s.log)) - s.echo.Use(otelecho.Middleware(s.config.Name)) + s.echo.Use( + log.EchoLogger( + s.log, + log.WithSkipper(skipper), + ), + ) + s.echo.Use( + otelecho.Middleware(s.config.Name, otelecho.WithSkipper(skipper)), + ) // Because we use metrics server middleware, if it is not available, our echo will not work. if s.meter != nil { s.echo.Use(otelMetrics.Middleware(s.meter, s.config.Name)) } - s.echo.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{ - LogContentLength: true, - LogLatency: true, - LogError: false, - LogMethod: true, - LogRequestID: true, - LogURI: true, - LogResponseSize: true, - LogURIPath: true, - LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error { - s.log.Infow( - fmt.Sprintf("[Request Middleware] REQUEST: uri: %v, status: %v\n", v.URI, v.Status), - logger.Fields{"URI": v.URI, "Status": v.Status}, - ) - return nil - }, - })) + //s.echo.Use( + // middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{ + // LogContentLength: true, + // LogLatency: true, + // LogError: false, + // LogMethod: true, + // LogRequestID: true, + // LogURI: true, + // LogResponseSize: true, + // LogURIPath: true, + // Skipper: func(c echo.Context) bool { + // return strings.Contains(c.Request().URL.Path, "swagger") || + // strings.Contains(c.Request().URL.Path, "metrics") || + // strings.Contains(c.Request().URL.Path, "health") || + // strings.Contains(c.Request().URL.Path, "favicon.ico") + // }, + // LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error { + // s.log.Infow( + // fmt.Sprintf( + // "[Request Middleware] REQUEST: uri: %v, status: %v\n", + // v.URI, + // v.Status, + // ), + // logger.Fields{"URI": v.URI, "Status": v.Status}, + // ) + // + // return nil + // }, + // }), + //) s.echo.Use(middleware.BodyLimit(constants.BodyLimit)) s.echo.Use(middleware.RequestID()) s.echo.Use(middleware.GzipWithConfig(middleware.GzipConfig{ - Level: constants.GzipLevel, - Skipper: func(c echo.Context) bool { - return strings.Contains(c.Request().URL.Path, "swagger") - }, + Level: constants.GzipLevel, + Skipper: skipper, })) } diff --git a/internal/pkg/http/custom_echo/middlewares/log/config.go b/internal/pkg/http/custom_echo/middlewares/log/config.go new file mode 100644 index 00000000..5e4cfbc1 --- /dev/null +++ b/internal/pkg/http/custom_echo/middlewares/log/config.go @@ -0,0 +1,27 @@ +package log + +import "github.com/labstack/echo/v4/middleware" + +// config defines the config for Logger middleware. +type config struct { + // Skipper defines a function to skip middleware. + Skipper middleware.Skipper +} + +// Option specifies instrumentation configuration options. +type Option interface { + apply(*config) +} + +type optionFunc func(*config) + +func (o optionFunc) apply(c *config) { + o(c) +} + +// WithSkipper specifies a skipper for allowing requests to skip generating spans. +func WithSkipper(skipper middleware.Skipper) Option { + return optionFunc(func(cfg *config) { + cfg.Skipper = skipper + }) +} diff --git a/internal/pkg/http/custom_echo/middlewares/log/log_middleware.go b/internal/pkg/http/custom_echo/middlewares/log/log_middleware.go index bfe739e7..a67949e2 100644 --- a/internal/pkg/http/custom_echo/middlewares/log/log_middleware.go +++ b/internal/pkg/http/custom_echo/middlewares/log/log_middleware.go @@ -7,14 +7,72 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" ) -func EchoLogger(logger logger.Logger) echo.MiddlewareFunc { +// EchoLogger returns echo middleware which will log incoming requests. +func EchoLogger(l logger.Logger, opts ...Option) echo.MiddlewareFunc { + cfg := config{} + for _, opt := range opts { + opt.apply(&cfg) + } + + if cfg.Skipper == nil { + cfg.Skipper = middleware.DefaultSkipper + } + + requestMiddleware := middleware.RequestLoggerWithConfig( + middleware.RequestLoggerConfig{ + Skipper: cfg.Skipper, + LogRequestID: true, + LogRemoteIP: true, + LogHost: true, + LogMethod: true, + LogURI: true, + LogUserAgent: true, + LogStatus: true, + LogError: true, + LogLatency: true, + LogContentLength: true, + LogResponseSize: true, + + LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error { + l.Infow( + fmt.Sprintf( + "[Request Middleware] REQUEST: uri: %v, status: %v\n", + v.URI, + v.Status, + ), + logger.Fields{ + "uri": v.URI, + "status": v.Status, + "id": v.RequestID, + "remote_ip": v.RemoteIP, + "host": v.Host, + "method": v.Method, + "user_agent": v.UserAgent, + "error": v.Error, + "latency": v.Latency.Nanoseconds(), + "latency_human": v.Latency.String(), + "bytes_in": v.ContentLength, + "bytes_out": v.ResponseSize, + }, + ) + + return nil + }, + }, + ) + return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { + if cfg.Skipper(c) { + return requestMiddleware(next)(c) + } + start := time.Now() - err := next(c) + err := requestMiddleware(next)(c) if err != nil { // handle echo error in this middleware and raise echo errorhandler func and our custom error handler (problem details handler) c.Error(err) @@ -42,13 +100,22 @@ func EchoLogger(logger logger.Logger) echo.MiddlewareFunc { n := res.Status switch { case n >= 500: - logger.Errorw("Echo logger middleware: Server error", fields) + l.Errorw( + "EchoServer logger middleware: Server error", + fields, + ) case n >= 400: - logger.Errorw("Echo logger middleware: Client error", fields) + l.Errorw( + "EchoServer logger middleware: Client error", + fields, + ) case n >= 300: - logger.Errorw("Echo logger middleware: Redirection", fields) + l.Errorw( + "EchoServer logger middleware: Redirection", + fields, + ) default: - logger.Infow("Echo logger middleware: Success", fields) + l.Infow("EchoServer logger middleware: Success", fields) } return nil diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/config.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/config.go new file mode 100644 index 00000000..698904cf --- /dev/null +++ b/internal/pkg/http/custom_echo/middlewares/otel_metrics/config.go @@ -0,0 +1,17 @@ +package otelmetrics + +import "github.com/labstack/echo/v4/middleware" + +type config struct { + Skipper middleware.Skipper +} + +type Option interface { + apply(*config) +} + +type optionFunc func(*config) + +func (o optionFunc) apply(c *config) { + o(c) +} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/request_status_middleware.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/request_status_middleware.go index 6b2139a1..12e34238 100644 --- a/internal/pkg/http/custom_echo/middlewares/otel_metrics/request_status_middleware.go +++ b/internal/pkg/http/custom_echo/middlewares/otel_metrics/request_status_middleware.go @@ -1,4 +1,4 @@ -package otelMetrics +package otelmetrics // ref:https://github.com/open-telemetry/opentelemetry-go/blob/main/example/prometheus/main.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/labstack/echo/v4" + "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" api "go.opentelemetry.io/otel/metric" ) @@ -17,8 +18,10 @@ var ( // Middleware adds request status metrics to the otel // ref: https://github.com/open-telemetry/opentelemetry-go/blob/main/example/prometheus/main.go -func Middleware(meter api.Meter, serviceName string) echo.MiddlewareFunc { - errorCounter, _ := meter.Float64Counter( +func Middleware(serviceName string) echo.MiddlewareFunc { + meter := otel.GetMeterProvider().Meter("echo") + + errorCounter, _ = meter.Float64Counter( //nolint:errcheck fmt.Sprintf("%s_error_http_requests_total", serviceName), api.WithDescription("The total number of error http requests"), ) diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/v0/prometheus.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/v0/prometheus.go new file mode 100644 index 00000000..c8eec024 --- /dev/null +++ b/internal/pkg/http/custom_echo/middlewares/otel_metrics/v0/prometheus.go @@ -0,0 +1,518 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: © 2017 LabStack and Echo contributors + +/* +Package prometheus provides middleware to add Prometheus metrics. + +Example: +``` +package main +import ( + + "github.com/labstack/echo/v4" + "github.com/labstack/echo-contrib/prometheus" + +) + + func main() { + e := echo.New() + // Enable metrics middleware + p := prometheus.NewPrometheus("echo", nil) + p.Use(e) + + e.Logger.Fatal(e.Start(":1323")) + } + +``` +*/ +package prometheus + +import ( + "bytes" + "errors" + "net/http" + "os" + "strconv" + "time" + + "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" + "github.com/labstack/gommon/log" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/prometheus/common/expfmt" +) + +var ( + defaultMetricPath = "/metrics" + defaultSubsystem = "echo" +) + +const ( + _ = iota // ignore first value by assigning to blank identifier + KB float64 = 1 << (10 * iota) + MB + GB + TB +) + +// reqDurBuckets is the buckets for request duration. Here, we use the prometheus defaults +// which are for ~10s request length max: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10} +var reqDurBuckets = prometheus.DefBuckets + +// reqSzBuckets is the buckets for request size. Here we define a spectrom from 1KB thru 1NB up to 10MB. +var reqSzBuckets = []float64{ + 1.0 * KB, + 2.0 * KB, + 5.0 * KB, + 10.0 * KB, + 100 * KB, + 500 * KB, + 1.0 * MB, + 2.5 * MB, + 5.0 * MB, + 10.0 * MB, +} + +// resSzBuckets is the buckets for response size. Here we define a spectrom from 1KB thru 1NB up to 10MB. +var resSzBuckets = []float64{ + 1.0 * KB, + 2.0 * KB, + 5.0 * KB, + 10.0 * KB, + 100 * KB, + 500 * KB, + 1.0 * MB, + 2.5 * MB, + 5.0 * MB, + 10.0 * MB, +} + +// Standard default metrics +// +// counter, counter_vec, gauge, gauge_vec, +// histogram, histogram_vec, summary, summary_vec +var reqCnt = &Metric{ + ID: "reqCnt", + Name: "requests_total", + Description: "How many HTTP requests processed, partitioned by status code and HTTP method.", + Type: "counter_vec", + Args: []string{"code", "method", "host", "url"}, +} + +var reqDur = &Metric{ + ID: "reqDur", + Name: "request_duration_seconds", + Description: "The HTTP request latencies in seconds.", + Args: []string{"code", "method", "host", "url"}, + Type: "histogram_vec", + Buckets: reqDurBuckets, +} + +var resSz = &Metric{ + ID: "resSz", + Name: "response_size_bytes", + Description: "The HTTP response sizes in bytes.", + Args: []string{"code", "method", "host", "url"}, + Type: "histogram_vec", + Buckets: resSzBuckets, +} + +var reqSz = &Metric{ + ID: "reqSz", + Name: "request_size_bytes", + Description: "The HTTP request sizes in bytes.", + Args: []string{"code", "method", "host", "url"}, + Type: "histogram_vec", + Buckets: reqSzBuckets, +} + +var standardMetrics = []*Metric{ + reqCnt, + reqDur, + resSz, + reqSz, +} + +/* +RequestCounterLabelMappingFunc is a function which can be supplied to the middleware to control +the cardinality of the request counter's "url" label, which might be required in some contexts. +For instance, if for a "/customer/:name" route you don't want to generate a time series for every +possible customer name, you could use this function: + + func(c echo.Context) string { + url := c.Request.URL.Path + for _, p := range c.Params { + if p.Key == "name" { + url = strings.Replace(url, p.Value, ":name", 1) + break + } + } + return url + } + +which would map "/customer/alice" and "/customer/bob" to their template "/customer/:name". +It can also be applied for the "Host" label +*/ +type RequestCounterLabelMappingFunc func(c echo.Context) string + +// Metric is a definition for the name, description, type, ID, and +// prometheus.Collector type (i.e. CounterVec, Summary, etc) of each metric +type Metric struct { + MetricCollector prometheus.Collector + ID string + Name string + Description string + Type string + Args []string + Buckets []float64 +} + +// Prometheus contains the metrics gathered by the instance and its path +// Deprecated: use echoprometheus package instead +type Prometheus struct { + reqCnt *prometheus.CounterVec + reqDur, reqSz, resSz *prometheus.HistogramVec + router *echo.Echo + listenAddress string + Ppg PushGateway + + MetricsList []*Metric + MetricsPath string + Subsystem string + Skipper middleware.Skipper + + RequestCounterURLLabelMappingFunc RequestCounterLabelMappingFunc + RequestCounterHostLabelMappingFunc RequestCounterLabelMappingFunc + + // Context string to use as a prometheus URL label + URLLabelFromContext string +} + +// PushGateway contains the configuration for pushing to a Prometheus pushgateway (optional) +type PushGateway struct { + // Push interval in seconds + //lint:ignore ST1011 renaming would be breaking change + PushIntervalSeconds time.Duration + + // Push Gateway URL in format http://domain:port + // where JOBNAME can be any string of your choice + PushGatewayURL string + + // pushgateway job name, defaults to "echo" + Job string +} + +// NewPrometheus generates a new set of metrics with a certain subsystem name +// Deprecated: use echoprometheus package instead +func NewPrometheus(subsystem string, skipper middleware.Skipper, customMetricsList ...[]*Metric) *Prometheus { + var metricsList []*Metric + if skipper == nil { + skipper = middleware.DefaultSkipper + } + + if len(customMetricsList) > 1 { + panic("Too many args. NewPrometheus( string, ).") + } else if len(customMetricsList) == 1 { + metricsList = customMetricsList[0] + } + + metricsList = append(metricsList, standardMetrics...) + + p := &Prometheus{ + MetricsList: metricsList, + MetricsPath: defaultMetricPath, + Subsystem: defaultSubsystem, + Skipper: skipper, + RequestCounterURLLabelMappingFunc: func(c echo.Context) string { + p := c.Path() // contains route path ala `/users/:id` + if p != "" { + return p + } + // as of Echo v4.10.1 path is empty for 404 cases (when router did not find any matching routes) + // in this case we use actual path from request to have some distinction in Prometheus + return c.Request().URL.Path + }, + RequestCounterHostLabelMappingFunc: func(c echo.Context) string { + return c.Request().Host + }, + } + + p.registerMetrics(subsystem) + + return p +} + +// SetPushGateway sends metrics to a remote pushgateway exposed on pushGatewayURL +// every pushInterval. Metrics are fetched from +func (p *Prometheus) SetPushGateway(pushGatewayURL string, pushInterval time.Duration) { + p.Ppg.PushGatewayURL = pushGatewayURL + p.Ppg.PushIntervalSeconds = pushInterval + p.startPushTicker() +} + +// SetPushGatewayJob job name, defaults to "echo" +func (p *Prometheus) SetPushGatewayJob(j string) { + p.Ppg.Job = j +} + +// SetListenAddress for exposing metrics on address. If not set, it will be exposed at the +// same address of the echo engine that is being used +// func (p *Prometheus) SetListenAddress(address string) { +// p.listenAddress = address +// if p.listenAddress != "" { +// p.router = echo.Echo().Router() +// } +// } + +// SetListenAddressWithRouter for using a separate router to expose metrics. (this keeps things like GET /metrics out of +// your content's access log). +// func (p *Prometheus) SetListenAddressWithRouter(listenAddress string, r *echo.Echo) { +// p.listenAddress = listenAddress +// if len(p.listenAddress) > 0 { +// p.router = r +// } +// } + +// SetMetricsPath set metrics paths +func (p *Prometheus) SetMetricsPath(e *echo.Echo) { + if p.listenAddress != "" { + p.router.GET(p.MetricsPath, prometheusHandler()) + p.runServer() + } else { + e.GET(p.MetricsPath, prometheusHandler()) + } +} + +func (p *Prometheus) runServer() { + if p.listenAddress != "" { + go p.router.Start(p.listenAddress) + } +} + +func (p *Prometheus) getMetrics() []byte { + out := &bytes.Buffer{} + metricFamilies, _ := prometheus.DefaultGatherer.Gather() + for i := range metricFamilies { + expfmt.MetricFamilyToText(out, metricFamilies[i]) + } + return out.Bytes() +} + +func (p *Prometheus) getPushGatewayURL() string { + h, _ := os.Hostname() + if p.Ppg.Job == "" { + p.Ppg.Job = "echo" + } + return p.Ppg.PushGatewayURL + "/metrics/job/" + p.Ppg.Job + "/instance/" + h +} + +func (p *Prometheus) sendMetricsToPushGateway(metrics []byte) { + req, err := http.NewRequest("POST", p.getPushGatewayURL(), bytes.NewBuffer(metrics)) + if err != nil { + log.Errorf("failed to create push gateway request: %v", err) + return + } + client := &http.Client{} + if _, err = client.Do(req); err != nil { + log.Errorf("Error sending to push gateway: %v", err) + } +} + +func (p *Prometheus) startPushTicker() { + ticker := time.NewTicker(time.Second * p.Ppg.PushIntervalSeconds) + go func() { + for range ticker.C { + p.sendMetricsToPushGateway(p.getMetrics()) + } + }() +} + +// NewMetric associates prometheus.Collector based on Metric.Type +// Deprecated: use echoprometheus package instead +func NewMetric(m *Metric, subsystem string) prometheus.Collector { + var metric prometheus.Collector + switch m.Type { + case "counter_vec": + metric = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Subsystem: subsystem, + Name: m.Name, + Help: m.Description, + }, + m.Args, + ) + case "counter": + metric = prometheus.NewCounter( + prometheus.CounterOpts{ + Subsystem: subsystem, + Name: m.Name, + Help: m.Description, + }, + ) + case "gauge_vec": + metric = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Subsystem: subsystem, + Name: m.Name, + Help: m.Description, + }, + m.Args, + ) + case "gauge": + metric = prometheus.NewGauge( + prometheus.GaugeOpts{ + Subsystem: subsystem, + Name: m.Name, + Help: m.Description, + }, + ) + case "histogram_vec": + metric = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Subsystem: subsystem, + Name: m.Name, + Help: m.Description, + Buckets: m.Buckets, + }, + m.Args, + ) + case "histogram": + metric = prometheus.NewHistogram( + prometheus.HistogramOpts{ + Subsystem: subsystem, + Name: m.Name, + Help: m.Description, + Buckets: m.Buckets, + }, + ) + case "summary_vec": + metric = prometheus.NewSummaryVec( + prometheus.SummaryOpts{ + Subsystem: subsystem, + Name: m.Name, + Help: m.Description, + }, + m.Args, + ) + case "summary": + metric = prometheus.NewSummary( + prometheus.SummaryOpts{ + Subsystem: subsystem, + Name: m.Name, + Help: m.Description, + }, + ) + } + return metric +} + +func (p *Prometheus) registerMetrics(subsystem string) { + for _, metricDef := range p.MetricsList { + metric := NewMetric(metricDef, subsystem) + if err := prometheus.Register(metric); err != nil { + log.Errorf("%s could not be registered in Prometheus: %v", metricDef.Name, err) + } + switch metricDef { + case reqCnt: + p.reqCnt = metric.(*prometheus.CounterVec) + case reqDur: + p.reqDur = metric.(*prometheus.HistogramVec) + case resSz: + p.resSz = metric.(*prometheus.HistogramVec) + case reqSz: + p.reqSz = metric.(*prometheus.HistogramVec) + } + metricDef.MetricCollector = metric + } +} + +// Use adds the middleware to the Echo engine. +func (p *Prometheus) Use(e *echo.Echo) { + e.Use(p.HandlerFunc) + p.SetMetricsPath(e) +} + +// HandlerFunc defines handler function for middleware +func (p *Prometheus) HandlerFunc(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + if c.Path() == p.MetricsPath { + return next(c) + } + if p.Skipper(c) { + return next(c) + } + + start := time.Now() + reqSz := computeApproximateRequestSize(c.Request()) + + err := next(c) + + status := c.Response().Status + if err != nil { + var httpError *echo.HTTPError + if errors.As(err, &httpError) { + status = httpError.Code + } + if status == 0 || status == http.StatusOK { + status = http.StatusInternalServerError + } + } + + elapsed := float64(time.Since(start)) / float64(time.Second) + + url := p.RequestCounterURLLabelMappingFunc(c) + if len(p.URLLabelFromContext) > 0 { + u := c.Get(p.URLLabelFromContext) + if u == nil { + u = "unknown" + } + url = u.(string) + } + + statusStr := strconv.Itoa(status) + p.reqDur.WithLabelValues(statusStr, c.Request().Method, p.RequestCounterHostLabelMappingFunc(c), url). + Observe(elapsed) + p.reqCnt.WithLabelValues(statusStr, c.Request().Method, p.RequestCounterHostLabelMappingFunc(c), url).Inc() + p.reqSz.WithLabelValues(statusStr, c.Request().Method, p.RequestCounterHostLabelMappingFunc(c), url). + Observe(float64(reqSz)) + + resSz := float64(c.Response().Size) + p.resSz.WithLabelValues(statusStr, c.Request().Method, p.RequestCounterHostLabelMappingFunc(c), url). + Observe(resSz) + + return err + } +} + +func prometheusHandler() echo.HandlerFunc { + h := promhttp.Handler() + return func(c echo.Context) error { + h.ServeHTTP(c.Response(), c.Request()) + return nil + } +} + +func computeApproximateRequestSize(r *http.Request) int { + s := 0 + if r.URL != nil { + s = len(r.URL.Path) + } + + s += len(r.Method) + s += len(r.Proto) + for name, values := range r.Header { + s += len(name) + for _, value := range values { + s += len(value) + } + } + s += len(r.Host) + + // N.B. r.Form and r.MultipartForm are assumed to be included in r.URL. + + if r.ContentLength != -1 { + s += int(r.ContentLength) + } + return s +} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/metric.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/metric.go new file mode 100644 index 00000000..0aa8b51a --- /dev/null +++ b/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/metric.go @@ -0,0 +1,193 @@ +package metricecho + +import ( + "context" + "fmt" + "time" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" +) + +// HTTPRecorderConfig lists all available configuration options for HTTPRecorder. +type HTTPRecorderConfig struct { + // Namespace is the metrics namespace that will be added to all metric configurations. It will be a prefix to each + // metric name. For example, if Namespace is "myapp", then requests_total metric will be myapp_http_requests_total + // (after namespace there is also the subsystem prefix, "http" in this case). + Namespace string + + // EnableTotalMetric whether to enable a metric to count the total number of http requests. + EnableTotalMetric bool + + // EnableDurMetric whether to enable a metric to track the duration of each request. + EnableDurMetric bool + + // EnableDurMetric whether to enable a metric that tells the number of current in-flight requests. + EnableInFlightMetric bool +} + +// HTTPCfg has the default configuration options for HTTPRecorder. +var HTTPCfg = HTTPRecorderConfig{ + EnableTotalMetric: true, + EnableDurMetric: true, + EnableInFlightMetric: true, +} + +func (c HTTPRecorderConfig) SetNamespace(v string) HTTPRecorderConfig { + c.Namespace = v + + return c +} + +// HTTPLabels will contain HTTP label values for each added metric. Not all labels apply to all metrics, read the +// documentation in each metric method to find out which labels are available for that metric. +type HTTPLabels struct { + // Method should be the HTTP method in the HTTP request. + Method string + // Code should be the HTTP status code in the HTTP response. If there is no response, the Code should be 0. + Code int + // Path is the request URL's path. Should not contain the query string and ideally it should only be the route + // definition. For example `/users/{ID}` instead of `/users/100`. + Path string +} + +// HTTPRecorder is a recorder of HTTP metrics for prometheus. Use NewHTTPRecorder to initialize it. +type HTTPRecorder struct { + cfg HTTPRecorderConfig + mp metric.MeterProvider + reqTotal metric.Int64Counter + reqDuration metric.Float64Histogram + reqInFlight metric.Int64UpDownCounter +} + +// NewHTTPRecorder creates a new HTTPRecorder. Calling this function will automatically register the new metrics to reg. +// If meter provider is nil, it will use otel's global provider. More information about configuration options in cfg can be +// found in documentation for HTTPRecorderConfig. +func NewHTTPRecorder(cfg HTTPRecorderConfig, meterProvider metric.MeterProvider) *HTTPRecorder { + if meterProvider == nil { + meterProvider = otel.GetMeterProvider() + } + + m := HTTPRecorder{ + cfg: cfg, + mp: meterProvider, + } + + if err := m.register(); err != nil { + // possible errors here include duplicate metric or same metrics with inconsistent labels or help strings. It is + // unlikely that it will happen if not by mistake. None the less we would like to know if such case occurs, hence + // a panic + panic(err) + } + + return &m +} + +func (h *HTTPRecorder) namespacedValue(v string) string { + if h.cfg.Namespace != "" { + return h.cfg.Namespace + "_" + v + } + + return v +} + +func (h *HTTPRecorder) register() error { + meter := h.mp.Meter("") + + if h.cfg.EnableTotalMetric { + reqTotal, err := meter.Int64Counter( + h.namespacedValue("http_requests_total"), + metric.WithDescription("The total number of requests"), + ) + if err != nil { + return fmt.Errorf("meter %s cannot set; %w", "http_requests_total", err) + } + + h.reqTotal = reqTotal + } + + if h.cfg.EnableDurMetric { + reqDuration, err := meter.Float64Histogram( + h.namespacedValue("request_duration_seconds"), + metric.WithDescription("The total duration of a request in seconds"), + ) + if err != nil { + return fmt.Errorf("meter %s cannot set; %w", "request_duration_seconds", err) + } + + h.reqDuration = reqDuration + } + + if h.cfg.EnableInFlightMetric { + reqInFlight, err := meter.Int64UpDownCounter( + h.namespacedValue("requests_inflight_total"), + metric.WithDescription("The current number of in-flight requests"), + ) + if err != nil { + return fmt.Errorf("meter %s cannot set; %w", "requests_inflight_total", err) + } + + h.reqInFlight = reqInFlight + } + + return nil +} + +// AddRequestToTotal adds 1 to the total number of requests. All labels should be specified. +func (h *HTTPRecorder) AddRequestToTotal(ctx context.Context, values HTTPLabels) { + if h.reqTotal == nil { + return + } + + h.reqTotal.Add(ctx, 1, + metric.WithAttributes( + attribute.String("method", values.Method), + attribute.Int("code", values.Code), + ), + ) +} + +// AddRequestDuration registers a request along with its duration. All labels should be specified. +func (h *HTTPRecorder) AddRequestDuration(ctx context.Context, duration time.Duration, values HTTPLabels) { + if h.reqDuration == nil { + return + } + + h.reqDuration.Record( + ctx, duration.Seconds(), + metric.WithAttributes( + attribute.String("method", values.Method), + attribute.String("path", values.Path), + attribute.Int("code", values.Code), + ), + ) +} + +// AddInFlightRequest Adds 1 to the number of current in-flight requests. All labels should be specified except for +// `Code`, as it will just be ignored. To remove a request use RemInFlightRequest. +func (h *HTTPRecorder) AddInFlightRequest(ctx context.Context, values HTTPLabels) { + if h.reqInFlight == nil { + return + } + + h.reqInFlight.Add( + ctx, + 1, + metric.WithAttributes(attribute.String("method", values.Method), attribute.String("path", values.Path)), + ) +} + +// RemInFlightRequest Remove 1 from the number of current in-flight requests. All labels should be specified except +// for `Code`, as it will just be ignored. Labels should match the ones passed to the equivalent AddInFlightRequest call. +func (h *HTTPRecorder) RemInFlightRequest(ctx context.Context, values HTTPLabels) { + if h.reqInFlight == nil { + return + } + + h.reqInFlight.Add( + ctx, + -1, + metric.WithAttributes(attribute.String("method", values.Method), attribute.String("path", values.Path)), + ) +} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/middleware.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/middleware.go new file mode 100644 index 00000000..c9a00f27 --- /dev/null +++ b/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/middleware.go @@ -0,0 +1,49 @@ +package metricecho + +import ( + "context" + "time" + + "github.com/labstack/echo/v4" +) + +// HTTPMetrics is an echo middleware to add metrics to rec for each HTTP request. +// If recorder config is nil, the middleware will use a recorder with default configuration. +func HTTPMetrics(cfg *HTTPRecorderConfig) echo.MiddlewareFunc { + if cfg == nil { + cfg = &HTTPCfg + } + + rec := NewHTTPRecorder(*cfg, nil) + + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) (err error) { + values := HTTPLabels{ + Method: c.Request().Method, + Path: c.Path(), + } + + rec.AddInFlightRequest(context.Background(), values) + + start := time.Now() + + defer func() { + elapsed := time.Since(start) + + if err != nil { + c.Error(err) + // don't return the error so that it's not handled again + err = nil + } + + values.Code = c.Response().Status + + rec.AddRequestToTotal(context.Background(), values) + rec.AddRequestDuration(context.Background(), elapsed, values) + rec.RemInFlightRequest(context.Background(), values) + }() + + return next(c) + } + } +} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/view.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/view.go new file mode 100644 index 00000000..10606b17 --- /dev/null +++ b/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/view.go @@ -0,0 +1,26 @@ +package metricecho + +import ( + "github.com/worldline-go/tell/tglobal" + "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/aggregation" +) + +func GetViews() []metric.View { + customBucketView := metric.NewView( + metric.Instrument{ + Name: "*request_duration_seconds", + }, + metric.Stream{ + Aggregation: aggregation.ExplicitBucketHistogram{ + Boundaries: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10}, + }, + }, + ) + + return []metric.View{customBucketView} +} + +func init() { + tglobal.MetricViews.Add("echo", GetViews()) +} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/v2/otel-meter.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/v2/otel-meter.go new file mode 100644 index 00000000..68f13864 --- /dev/null +++ b/internal/pkg/http/custom_echo/middlewares/otel_metrics/v2/otel-meter.go @@ -0,0 +1,446 @@ +// Package otelmetric provides middleware to add opentelemetry metrics and Prometheus exporter. +package echootelmetrics + +import ( + "errors" + "net/http" + "time" + + "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" + realprometheus "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/prometheus" + "go.opentelemetry.io/otel/metric" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/aggregation" + "go.opentelemetry.io/otel/sdk/resource" + semconv "go.opentelemetry.io/otel/semconv/v1.20.0" +) + +// Meter can be a global/package variable. +var meter = otel.GetMeterProvider().Meter("echo") + +var ( + defaultMetricPath = "/metrics" + defaultSubsystem = "echo" +) + +const ( + _ = iota // ignore first value by assigning to blank identifier + _KB float64 = 1 << (10 * iota) + _MB + _GB + _TB +) + +const ( + unitDimensionless = "1" + unitBytes = "By" + unitMilliseconds = "ms" +) + +// reqDurBucketsMilliseconds is the buckets for request duration. Here, we use the prometheus defaults +// which are for ~10s request length max: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10} +var reqDurBucketsMilliseconds = []float64{ + .005 * 1000, + .01 * 1000, + .025 * 1000, + .05 * 1000, + .1 * 1000, + .25 * 1000, + .5 * 1000, + 1 * 1000, + 2.5 * 1000, + 5 * 1000, + 10 * 1000, +} + +var reqDurBucketsSeconds = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10} + +// byteBuckets is the buckets for request/response size. Here we define a spectrom from 1KB thru 1NB up to 10MB. +var byteBuckets = []float64{ + 1.0 * _KB, + 2.0 * _KB, + 5.0 * _KB, + 10.0 * _KB, + 100 * _KB, + 500 * _KB, + 1.0 * _MB, + 2.5 * _MB, + 5.0 * _MB, + 10.0 * _MB, +} + +/* +RequestCounterLabelMappingFunc is a function which can be supplied to the middleware to control +the cardinality of the request counter's "url" label, which might be required in some contexts. +For instance, if for a "/customer/:name" route you don't want to generate a time series for every +possible customer name, you could use this function: + + func(c echo.Context) string { + url := c.Request.URL.Path + for _, p := range c.Params { + if p.Key == "name" { + url = strings.Replace(url, p.Value, ":name", 1) + break + } + } + return url + } + +which would map "/customer/alice" and "/customer/bob" to their template "/customer/:name". +It can also be applied for the "Host" label +*/ +type RequestCounterLabelMappingFunc func(c echo.Context) string + +// MiddlewareConfig contains the configuration for creating prometheus middleware collecting several default metrics. +type MiddlewareConfig struct { + // Skipper defines a function to skip middleware. + Skipper middleware.Skipper + + // Namespace is components of the fully-qualified name of the Metric (created by joining Namespace,Subsystem and Name components with "_") + // Optional + Namespace string + + // Subsystem is components of the fully-qualified name of the Metric (created by joining Namespace,Subsystem and Name components with "_") + // Defaults to: "echo" + Subsystem string + + ServiceVersion string + + // run as [echo prometheus middleware](https://github.com/labstack/echo-contrib/blob/master/echoprometheus) compatible mode + CompatibleMode bool + + MetricsPath string + + RequestCounterURLLabelMappingFunc RequestCounterLabelMappingFunc + RequestCounterHostLabelMappingFunc RequestCounterLabelMappingFunc + + // Registry is the prometheus registry that will be used as the default Registerer and + // Gatherer if these are not specified. + Registry *realprometheus.Registry + + // Registerer sets the prometheus.Registerer instance the middleware will register these metrics with. + // Defaults to: prometheus.DefaultRegisterer + Registerer realprometheus.Registerer + + // Gatherer is the prometheus gatherer to gather metrics with. + // If not specified the Registry will be used as default. + Gatherer realprometheus.Gatherer +} + +// Prometheus contains the metrics gathered by the instance and its path +type Prometheus struct { + reqCnt metric.Int64Counter + reqDurCompatible metric.Float64Histogram + reqDur metric.Int64Histogram + reqSz, resSz metric.Int64Histogram + router *echo.Echo + + *MiddlewareConfig +} + +// NewPrometheus generates a new set of metrics with a certain subsystem name +func NewPrometheus(config MiddlewareConfig) *Prometheus { + if config.Skipper == nil { + config.Skipper = middleware.DefaultSkipper + } + + if config.Subsystem == "" { + config.Subsystem = defaultSubsystem + } + + if config.MetricsPath == "" { + config.MetricsPath = defaultMetricPath + } + + registry := realprometheus.NewRegistry() + + if config.Registry == nil { + config.Registry = registry + } + + if config.Registerer == nil { + config.Registerer = registry + } + if config.Gatherer == nil { + config.Gatherer = registry + } + + if config.RequestCounterURLLabelMappingFunc == nil { + config.RequestCounterURLLabelMappingFunc = func(c echo.Context) string { + // contains route path ala `/users/:id` + // as of Echo v4.10.1 path is empty for 404 cases (when router did not find any matching routes) + return c.Path() + } + } + + if config.RequestCounterHostLabelMappingFunc == nil { + config.RequestCounterHostLabelMappingFunc = func(c echo.Context) string { + return c.Request().Host + } + } + + p := &Prometheus{ + MiddlewareConfig: &config, + } + + var err error + // Standard default metrics + p.reqCnt, err = meter.Int64Counter( + // the result name is `requests_total` + // https://github.com/open-telemetry/opentelemetry-go/blob/46f2ce5ca6adaa264c37cdbba251c9184a06ed7f/exporters/prometheus/exporter.go#L74 + // the exporter will enforce the `_total` suffix for counter, so we do not need it here + "requests", + // see https://github.com/open-telemetry/opentelemetry-go/pull/3776 + // The go.opentelemetry.io/otel/metric/unit package is deprecated. Setup the equivalent unit string instead. (#3776) + // Setup "1" instead of unit.Dimensionless + // Setup "By" instead of unit.Bytes + // Setup "ms" instead of unit.Milliseconds + + // the exported metrics name will force suffix by unit, see + // https://github.com/open-telemetry/opentelemetry-go/blob/46f2ce5ca6adaa264c37cdbba251c9184a06ed7f/exporters/prometheus/exporter.go#L315 + // + // var unitSuffixes = map[string]string{ + // "1": "_ratio", + // "By": "_bytes", + // "ms": "_milliseconds", + // } + // disable this behaviour by using `prometheus.WithoutUnits()` option + // or hack: do not set unit for counter to avoid the `_ratio` suffix + metric.WithDescription("How many HTTP requests processed, partitioned by status code and HTTP method."), + ) + + if err != nil { + panic(err) + } + + if !p.CompatibleMode { + p.reqDur, err = meter.Int64Histogram( + "request_duration", + metric.WithUnit(unitMilliseconds), + metric.WithDescription("The HTTP request latencies in milliseconds."), + ) + if err != nil { + panic(err) + } + } else { + p.reqDurCompatible, err = meter.Float64Histogram( + "request_duration_seconds", + metric.WithUnit("s"), + metric.WithDescription("The HTTP request latencies in seconds."), + ) + if err != nil { + panic(err) + } + } + + p.resSz, err = meter.Int64Histogram( + "response_size", + metric.WithUnit(unitBytes), + metric.WithDescription("The HTTP response sizes in bytes."), + ) + if err != nil { + panic(err) + } + + p.reqSz, err = meter.Int64Histogram( + "request_size", + metric.WithUnit(unitBytes), + metric.WithDescription("The HTTP request sizes in bytes."), + ) + if err != nil { + panic(err) + } + + return p +} + +// SetMetricsExporterRoute set metrics paths +func (p *Prometheus) SetMetricsExporterRoute(e *echo.Echo) { + e.GET(p.MetricsPath, p.ExporterHandler()) +} + +// Setup adds the middleware to the Echo engine. +func (p *Prometheus) Setup(e *echo.Echo) { + e.Use(p.HandlerFunc) + p.SetMetricsExporterRoute(e) +} + +// HandlerFunc defines handler function for middleware +func (p *Prometheus) HandlerFunc(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + if c.Path() == p.MetricsPath { + return next(c) + } + if p.Skipper(c) { + return next(c) + } + + start := time.Now() + reqSz := computeApproximateRequestSize(c.Request()) + + err := next(c) + + status := c.Response().Status + if err != nil { + var httpError *echo.HTTPError + if errors.As(err, &httpError) { + status = httpError.Code + } + if status == 0 || status == http.StatusOK { + status = http.StatusInternalServerError + } + } + + elapsed := time.Since(start) / time.Millisecond + + url := p.RequestCounterURLLabelMappingFunc(c) + host := p.RequestCounterHostLabelMappingFunc(c) + + if !p.CompatibleMode { + p.reqDur.Record(c.Request().Context(), int64(elapsed), metric.WithAttributes( + attribute.Int("code", status), + attribute.String("method", c.Request().Method), + attribute.String("host", host), + attribute.String("url", url))) + } else { + elapsedSeconds := float64(elapsed) / float64(1000) + p.reqDurCompatible.Record(c.Request().Context(), elapsedSeconds, metric.WithAttributes( + attribute.Int("code", status), + attribute.String("method", c.Request().Method), + attribute.String("host", host), + attribute.String("url", url))) + } + + // "code", "method", "host", "url" + p.reqCnt.Add(c.Request().Context(), 1, + metric.WithAttributes( + attribute.Int("code", status), + attribute.String("method", c.Request().Method), + attribute.String("host", host), + attribute.String("url", url))) + + p.reqSz.Record(c.Request().Context(), int64(reqSz), + metric.WithAttributes( + attribute.Int("code", status), + attribute.String("method", c.Request().Method), + attribute.String("host", host), + attribute.String("url", url))) + + resSz := float64(c.Response().Size) + p.resSz.Record(c.Request().Context(), int64(resSz), + metric.WithAttributes( + attribute.Int("code", status), + attribute.String("method", c.Request().Method), + attribute.String("host", host), + attribute.String("url", url))) + + return err + } +} + +func (p *Prometheus) initMetricsExporter() *prometheus.Exporter { + serviceName := p.Subsystem + res, err := resource.Merge(resource.Default(), + resource.NewSchemaless( + semconv.ServiceName(serviceName), + semconv.ServiceVersion(p.ServiceVersion), + )) + if err != nil { + panic(err) + } + + opts := []prometheus.Option{ + prometheus.WithRegisterer(p.Registerer), + prometheus.WithNamespace(serviceName), + } + if p.CompatibleMode { + opts = append(opts, prometheus.WithoutScopeInfo()) + } + exporter, err := prometheus.New(opts...) + if err != nil { + panic(err) + } + + durationBucketsView := sdkmetric.NewView( + sdkmetric.Instrument{Name: "*_duration_milliseconds"}, + sdkmetric.Stream{Aggregation: aggregation.ExplicitBucketHistogram{ + Boundaries: reqDurBucketsMilliseconds, + }}, + ) + if p.CompatibleMode { + durationBucketsView = sdkmetric.NewView( + sdkmetric.Instrument{Name: "*_duration_seconds"}, + sdkmetric.Stream{Aggregation: aggregation.ExplicitBucketHistogram{ + Boundaries: reqDurBucketsSeconds, + }}, + ) + } + + reqBytesBucketsView := sdkmetric.NewView( + sdkmetric.Instrument{Name: "*request_size"}, + sdkmetric.Stream{Aggregation: aggregation.ExplicitBucketHistogram{ + Boundaries: byteBuckets, + }}, + ) + + rspBytesBucketsView := sdkmetric.NewView( + sdkmetric.Instrument{Name: "*response_size"}, + sdkmetric.Stream{Aggregation: aggregation.ExplicitBucketHistogram{ + Boundaries: byteBuckets, + }}, + ) + + defaultView := sdkmetric.NewView(sdkmetric.Instrument{Name: "*", Kind: sdkmetric.InstrumentKindCounter}, + sdkmetric.Stream{}) + + provider := sdkmetric.NewMeterProvider( + sdkmetric.WithResource(res), + // view see https://github.com/open-telemetry/opentelemetry-go/blob/v1.11.2/exporters/prometheus/exporter_test.go#L291 + sdkmetric.WithReader(exporter), + sdkmetric.WithView(durationBucketsView, reqBytesBucketsView, rspBytesBucketsView, defaultView), + ) + + otel.SetMeterProvider(provider) + + return exporter +} + +func (p *Prometheus) ExporterHandler() echo.HandlerFunc { + p.initMetricsExporter() + + h := promhttp.HandlerFor(p.Gatherer, promhttp.HandlerOpts{}) + + return func(c echo.Context) error { + h.ServeHTTP(c.Response(), c.Request()) + return nil + } +} + +func computeApproximateRequestSize(r *http.Request) int { + s := 0 + if r.URL != nil { + s = len(r.URL.Path) + } + + s += len(r.Method) + s += len(r.Proto) + for name, values := range r.Header { + s += len(name) + for _, value := range values { + s += len(value) + } + } + s += len(r.Host) + + // N.B. r.Form and r.MultipartForm are assumed to be included in r.URL. + + if r.ContentLength != -1 { + s += int(r.ContentLength) + } + return s +} diff --git a/internal/pkg/http/custom_echo/otel/tracing/utils.go b/internal/pkg/http/custom_echo/utils/tracing.go similarity index 84% rename from internal/pkg/http/custom_echo/otel/tracing/utils.go rename to internal/pkg/http/custom_echo/utils/tracing.go index 351ff2ac..bea19d42 100644 --- a/internal/pkg/http/custom_echo/otel/tracing/utils.go +++ b/internal/pkg/http/custom_echo/utils/tracing.go @@ -1,4 +1,4 @@ -package tracing +package utils import ( "context" @@ -19,7 +19,9 @@ func TraceHttpErrFromSpan(span trace.Span, err error) error { if err != nil { stackTraceError := errorUtils.ErrorsWithStack(err) span.SetStatus(codes.Error, "") - span.SetAttributes(attribute.String(constants.Otel.HttpErrorMessage, stackTraceError)) + span.SetAttributes( + attribute.String(constants.Otel.HttpErrorMessage, stackTraceError), + ) if customErrors.IsCustomError(err) { httpError := problemDetails.ParseError(err) span.SetAttributes(semconv.HTTPStatusCode(httpError.GetStatus())) @@ -36,7 +38,9 @@ func TraceHttpErrFromSpanWithCode(span trace.Span, err error, code int) error { stackTraceError := errorUtils.ErrorsWithStack(err) span.SetStatus(codes.Error, "") span.SetAttributes(semconv.HTTPStatusCode(code)) - span.SetAttributes(attribute.String(constants.Otel.HttpErrorMessage, stackTraceError)) + span.SetAttributes( + attribute.String(constants.Otel.HttpErrorMessage, stackTraceError), + ) span.RecordError(err) } @@ -51,7 +55,9 @@ func TraceHttpErrFromContext(ctx context.Context, err error) error { if err != nil { stackTraceError := errorUtils.ErrorsWithStack(err) span.SetStatus(codes.Error, "") - span.SetAttributes(attribute.String(constants.Otel.HttpErrorMessage, stackTraceError)) + span.SetAttributes( + attribute.String(constants.Otel.HttpErrorMessage, stackTraceError), + ) span.RecordError(err) } diff --git a/internal/pkg/logger/config/log_options.go b/internal/pkg/logger/config/log_options.go index 6163960b..6af62b1d 100644 --- a/internal/pkg/logger/config/log_options.go +++ b/internal/pkg/logger/config/log_options.go @@ -15,6 +15,7 @@ type LogOptions struct { LogLevel string `mapstructure:"level"` LogType models.LogType `mapstructure:"logType"` CallerEnabled bool `mapstructure:"callerEnabled"` + EnableTracing bool `mapstructure:"enableTracing" default:"true"` } func ProvideLogConfig(env environemnt.Environment) (*LogOptions, error) { diff --git a/internal/pkg/logger/external/fxlog/fx.go b/internal/pkg/logger/external/fxlog/fx.go index 934049ff..bab76ffc 100644 --- a/internal/pkg/logger/external/fxlog/fx.go +++ b/internal/pkg/logger/external/fxlog/fx.go @@ -139,7 +139,7 @@ func (l *FxCustomLogger) LogEvent(event fxevent.Event) { logger.Fields{"error": e.Err}, ) } else { - l.Debugw("initialized custom fxevent.Logger", logger.Fields{"function": e.ConstructorName}) + l.Debugw("initialized custom fxevent.logger", logger.Fields{"function": e.ConstructorName}) } } } diff --git a/internal/pkg/logger/external/gromlog/gorm.go b/internal/pkg/logger/external/gromlog/gorm.go index 65a2577f..e39f0f5c 100644 --- a/internal/pkg/logger/external/gromlog/gorm.go +++ b/internal/pkg/logger/external/gromlog/gorm.go @@ -20,7 +20,7 @@ type GormCustomLogger struct { func NewGormCustomLogger(logger logger.Logger) *GormCustomLogger { //cfg, err := config.ProvideLogConfig() // - //var logger logger.Logger + //var logger logger.logger //if cfg.LogType == models.Logrus && err != nil { // logger = logrous.NewLogrusLogger(cfg, constants.Dev) //} else { diff --git a/internal/pkg/logger/logrous/logrous_logger.go b/internal/pkg/logger/logrous/logrous_logger.go index 277bd89a..efa57373 100644 --- a/internal/pkg/logger/logrous/logrous_logger.go +++ b/internal/pkg/logger/logrous/logrous_logger.go @@ -12,6 +12,7 @@ import ( "github.com/nolleh/caption_json_formatter" "github.com/sirupsen/logrus" + "github.com/uptrace/opentelemetry-go-extra/otellogrus" ) type logrusLogger struct { @@ -32,7 +33,10 @@ var loggerLevelMap = map[string]logrus.Level{ } // NewLogrusLogger creates a new logrus logger -func NewLogrusLogger(cfg *config2.LogOptions, env environemnt.Environment) logger.Logger { +func NewLogrusLogger( + cfg *config2.LogOptions, + env environemnt.Environment, +) logger.Logger { logrusLogger := &logrusLogger{level: cfg.LogLevel, logOptions: cfg} logrusLogger.initLogger(env) @@ -65,6 +69,16 @@ func (l *logrusLogger) initLogger(env environemnt.Environment) { logrusLogger.SetFormatter(&caption_json_formatter.Formatter{PrettyPrint: true}) } + if l.logOptions.EnableTracing { + // Instrument logrus. + logrus.AddHook(otellogrus.NewHook(otellogrus.WithLevels( + logrus.PanicLevel, + logrus.FatalLevel, + logrus.ErrorLevel, + logrus.WarnLevel, + ))) + } + l.logger = logrusLogger } @@ -190,6 +204,8 @@ func (l *logrusLogger) GrpcClientInterceptorLogger( ) } -func (l *logrusLogger) mapToFields(fields map[string]interface{}) *logrus.Entry { +func (l *logrusLogger) mapToFields( + fields map[string]interface{}, +) *logrus.Entry { return l.logger.WithFields(logrus.Fields{"ss": 1}) } diff --git a/internal/pkg/logger/zap/zap_logger.go b/internal/pkg/logger/zap/zap_logger.go index 7040eddf..a0ac80fd 100644 --- a/internal/pkg/logger/zap/zap_logger.go +++ b/internal/pkg/logger/zap/zap_logger.go @@ -60,6 +60,7 @@ func (l *zapLogger) getLoggerLevel() zapcore.Level { if !exist { return zapcore.DebugLevel } + return level } @@ -114,8 +115,10 @@ func (l *zapLogger) initLogger(env environemnt.Environment) { logger := zap.New(core, options...) - // add logs as events to tracing - logger = otelzap.New(logger).Logger + if l.logOptions.EnableTracing { + // add logs as events to tracing + logger = otelzap.New(logger).Logger + } l.logger = logger l.sugarLogger = logger.Sugar() diff --git a/internal/pkg/mongodb/health.go b/internal/pkg/mongodb/health.go index e48af264..7a132610 100644 --- a/internal/pkg/mongodb/health.go +++ b/internal/pkg/mongodb/health.go @@ -3,7 +3,7 @@ package mongodb import ( "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health/contracts" "go.mongodb.org/mongo-driver/mongo" ) @@ -12,7 +12,7 @@ type mongoHealthChecker struct { client *mongo.Client } -func NewMongoHealthChecker(client *mongo.Client) health.Health { +func NewMongoHealthChecker(client *mongo.Client) contracts.Health { return &mongoHealthChecker{client} } diff --git a/internal/pkg/mongodb/mongo_fx.go b/internal/pkg/mongodb/mongo_fx.go index b3336d0b..6d1890f7 100644 --- a/internal/pkg/mongodb/mongo_fx.go +++ b/internal/pkg/mongodb/mongo_fx.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "go.mongodb.org/mongo-driver/mongo" @@ -26,7 +26,7 @@ var ( NewMongoDB, fx.Annotate( NewMongoHealthChecker, - fx.As(new(health.Health)), + fx.As(new(contracts.Health)), fx.ResultTags(fmt.Sprintf(`group:"%s"`, "healths")), ), ) diff --git a/internal/pkg/mongodb/mongo_options.go b/internal/pkg/mongodb/mongo_options.go index 46ba2f6b..a7c912de 100644 --- a/internal/pkg/mongodb/mongo_options.go +++ b/internal/pkg/mongodb/mongo_options.go @@ -9,15 +9,20 @@ import ( ) type MongoDbOptions struct { - Host string `mapstructure:"host"` - Port int `mapstructure:"port"` - User string `mapstructure:"user"` - Password string `mapstructure:"password"` - Database string `mapstructure:"database"` - UseAuth bool `mapstructure:"useAuth"` + Host string `mapstructure:"host"` + Port int `mapstructure:"port"` + User string `mapstructure:"user"` + Password string `mapstructure:"password"` + Database string `mapstructure:"database"` + UseAuth bool `mapstructure:"useAuth"` + EnableTracing bool `mapstructure:"enableTracing" default:"true"` } -func provideConfig(environment environemnt.Environment) (*MongoDbOptions, error) { - optionName := strcase.ToLowerCamel(typeMapper.GetTypeNameByT[MongoDbOptions]()) +func provideConfig( + environment environemnt.Environment, +) (*MongoDbOptions, error) { + optionName := strcase.ToLowerCamel( + typeMapper.GetTypeNameByT[MongoDbOptions](), + ) return config.BindConfigKey[*MongoDbOptions](optionName, environment) } diff --git a/internal/pkg/mongodb/mongodb.go b/internal/pkg/mongodb/mongodb.go index 5098b90d..338f079e 100644 --- a/internal/pkg/mongodb/mongodb.go +++ b/internal/pkg/mongodb/mongodb.go @@ -34,8 +34,6 @@ func NewMongoDB(cfg *MongoDbOptions) (*mongo.Client, error) { SetMaxConnIdleTime(maxConnIdleTime). SetMinPoolSize(minPoolSize). SetMaxPoolSize(maxPoolSize) - // add tracing - opt.Monitor = otelmongo.NewMonitor() if cfg.UseAuth { opt = opt.SetAuth( @@ -49,6 +47,11 @@ func NewMongoDB(cfg *MongoDbOptions) (*mongo.Client, error) { return nil, err } + if cfg.EnableTracing { + // add tracing + opt.Monitor = otelmongo.NewMonitor() + } + // setup https://github.com/Kamva/mgm err = mgm.SetDefaultConfig(nil, cfg.Database, opt) if err != nil { diff --git a/internal/pkg/otel/config/open_telemtry_options.go b/internal/pkg/otel/config/open_telemtry_options.go deleted file mode 100644 index 7a68c7a8..00000000 --- a/internal/pkg/otel/config/open_telemtry_options.go +++ /dev/null @@ -1,46 +0,0 @@ -package config - -import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" - - "github.com/iancoleman/strcase" -) - -type OpenTelemetryOptions struct { - Enabled bool `mapstructure:"enabled"` - ServiceName string `mapstructure:"serviceName"` - InstrumentationName string `mapstructure:"instrumentationName"` - Id int64 `mapstructure:"id"` - AlwaysOnSampler bool `mapstructure:"alwaysOnSampler"` - JaegerExporterOptions *JaegerExporterOptions `mapstructure:"jaegerExporterOptions"` - ZipkinExporterOptions *ZipkinExporterOptions `mapstructure:"zipkinExporterOptions"` - OTelMetricsOptions *OTelMetricsOptions `mapstructure:"otelMetricsOptions"` - UseStdout bool `mapstructure:"useStdout"` -} - -type JaegerExporterOptions struct { - OtlpEndpoint string `mapstructure:"otlpEndpoint"` -} - -type ZipkinExporterOptions struct { - Url string `mapstructure:"url"` -} - -type OTelMetricsOptions struct { - Host string `mapstructure:"host"` - Port string `mapstructure:"port"` - Name string `mapstructure:"name"` - MetricsRoutePath string `mapstructure:"metricsRoutePath"` -} - -func ProvideOtelConfig( - environment environemnt.Environment, -) (*OpenTelemetryOptions, error) { - optionName := strcase.ToLowerCamel( - typeMapper.GetTypeNameByT[OpenTelemetryOptions](), - ) - - return config.BindConfigKey[*OpenTelemetryOptions](optionName, environment) -} diff --git a/internal/pkg/otel/metrics/custom_meter.go b/internal/pkg/otel/metrics/custom_meter.go new file mode 100644 index 00000000..47d2cbf5 --- /dev/null +++ b/internal/pkg/otel/metrics/custom_meter.go @@ -0,0 +1,22 @@ +package metrics + +import ( + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/metric" +) + +type AppMetrics interface { + metric.Meter +} + +type appMetrics struct { + metric.Meter +} + +func NewAppMeter(name string, opts ...metric.MeterOption) AppMetrics { + // Meter can be a global/package variable. + // https://github.com/open-telemetry/opentelemetry-go/blob/46f2ce5ca6adaa264c37cdbba251c9184a06ed7f/metric.go#LL35C6-L35C11 + meter := otel.Meter(name, opts...) + + return &appMetrics{Meter: meter} +} diff --git a/internal/pkg/otel/metrics/metrics.go b/internal/pkg/otel/metrics/metrics.go index 9534b1ec..c4300b35 100644 --- a/internal/pkg/otel/metrics/metrics.go +++ b/internal/pkg/otel/metrics/metrics.go @@ -1,81 +1,280 @@ package metrics +// https://github.com/riferrei/otel-with-golang/blob/main/main.go +// https://github.com/open-telemetry/opentelemetry-go/blob/main/example/prometheus/main.go + import ( "context" + "time" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/config" "emperror.dev/errors" "github.com/labstack/echo/v4" - "github.com/labstack/echo/v4/middleware" "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/samber/lo" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" "go.opentelemetry.io/otel/exporters/prometheus" - api "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/resource" + semconv "go.opentelemetry.io/otel/semconv/v1.21.0" ) type OtelMetrics struct { - Config *config.OpenTelemetryOptions - Logger logger.Logger - Meter api.Meter - Echo *echo.Echo + config *MetricsOptions + logger logger.Logger + appMetrics AppMetrics + environment environemnt.Environment + provider *metric.MeterProvider } // NewOtelMetrics adds otel metrics -// https://github.com/open-telemetry/opentelemetry-go/blob/main/example/prometheus/main.go func NewOtelMetrics( - config *config.OpenTelemetryOptions, + config *MetricsOptions, logger logger.Logger, + environment environemnt.Environment, ) (*OtelMetrics, error) { if config == nil { return nil, errors.New("metrics config can't be nil") } - e := echo.New() - e.HideBanner = false + otelMetrics := &OtelMetrics{ + config: config, + logger: logger, + environment: environment, + } + + resource, err := otelMetrics.newResource() + if err != nil { + return nil, errors.WrapIf(err, "failed to create resource") + } + + appMetrics, err := otelMetrics.initMetrics(resource) + if err != nil { + return nil, err + } + + otelMetrics.appMetrics = appMetrics + + return otelMetrics, nil +} + +func (o *OtelMetrics) Shutdown(ctx context.Context) error { + return o.provider.Shutdown(ctx) +} + +func (o *OtelMetrics) newResource() (*resource.Resource, error) { + // https://github.com/uptrace/uptrace-go/blob/master/example/otlp-traces/main.go#L49C1-L56C5 + resource, err := resource.New( + context.Background(), + resource.WithFromEnv(), + resource.WithTelemetrySDK(), + resource.WithHost(), + resource.WithOS(), + resource.WithSchemaURL(semconv.SchemaURL), + resource.WithAttributes( + semconv.ServiceName(o.config.ServiceName), + semconv.ServiceVersion(o.config.Version), + attribute.String("environment", o.environment.GetEnvironmentName()), + semconv.TelemetrySDKVersionKey.String("v1.21.0"), // semconv version + semconv.TelemetrySDKLanguageGo, + )) - // The exporter embeds a default OpenTelemetry Reader and - // implements prometheus.Collector, allowing it to be used as - // both a Reader and Collector. - exporter, err := prometheus.New() + return resource, err +} + +func (o *OtelMetrics) initMetrics( + resource *resource.Resource, +) (AppMetrics, error) { + metricsExporter, err := o.configExporters() if err != nil { - logger.Fatal(err) + return nil, err } - provider := metric.NewMeterProvider(metric.WithReader(exporter)) - meter := provider.Meter( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics", + + batchExporters := lo.Map( + metricsExporter, + func(item metric.Reader, index int) metric.Option { + return metric.WithReader(item) + }, ) - return &OtelMetrics{Config: config, Meter: meter, Logger: logger, Echo: e}, nil + // https://opentelemetry.io/docs/instrumentation/go/exporting_data/#resources + // Resources are a special type of attribute that apply to all spans generated by a process + opts := append( + batchExporters, + metric.WithResource(resource), + ) + + // otel library collects metrics and send this metrics to some exporter like console or prometheus + provider := metric.NewMeterProvider(opts...) + + // Register our MeterProvider as the global so any imported + // instrumentation in the future will default to using it. + otel.SetMeterProvider(provider) + o.provider = provider + + appMeter := NewAppMeter(o.config.InstrumentationName) + + return appMeter, nil } -func (o *OtelMetrics) Run() error { - o.Echo.Use(middleware.RecoverWithConfig(middleware.RecoverConfig{ - StackSize: 1 << 10, // 1 KB - DisablePrintStack: true, - DisableStackAll: true, - })) +func (o *OtelMetrics) configExporters() ([]metric.Reader, error) { + ctx := context.Background() - var metricsPath string - if o.Config.OTelMetricsOptions.MetricsRoutePath == "" { - metricsPath = "/metrics" - } else { - metricsPath = o.Config.OTelMetricsOptions.MetricsRoutePath + var exporters []metric.Reader + + // use some otel collector endpoints + metricOpts := []otlpmetricgrpc.Option{ + otlpmetricgrpc.WithTimeout(5 * time.Second), + otlpmetricgrpc.WithInsecure(), } - o.Echo.GET(metricsPath, echo.WrapHandler(promhttp.Handler())) - o.Logger.Infof("serving metrics at localhost:%s/metrics", o.Config.OTelMetricsOptions.Port) - err := o.Echo.Start(o.Config.OTelMetricsOptions.Port) + if !o.config.UseOTLP { //nolint:nestif + + if o.config.UseStdout { + console, err := stdoutmetric.New() + if err != nil { + return nil, errors.WrapIf( + err, + "error creating console exporter", + ) + } + + consoleMetricExporter := metric.NewPeriodicReader( + console, + // Default is 1m. Set to 3s for demonstrative purposes. + metric.WithInterval(3*time.Second)) + + exporters = append(exporters, consoleMetricExporter) + } + + if o.config.ElasticApmExporterOptions != nil { + // https://www.elastic.co/guide/en/apm/guide/current/open-telemetry.html + // https://www.elastic.co/guide/en/apm/guide/current/open-telemetry-direct.html#instrument-apps-otel + // https://github.com/anilsenay/go-opentelemetry-examples/blob/elastic/cmd/main.go#L35 + metricOpts = append( + metricOpts, + otlpmetricgrpc.WithEndpoint( + o.config.ElasticApmExporterOptions.OTLPEndpoint, + ), + otlpmetricgrpc.WithHeaders( + o.config.ElasticApmExporterOptions.OTLPHeaders, + ), + ) + + // send otel traces to jaeger builtin collector endpoint (default grpc port: 4317) + // https://opentelemetry.io/docs/collector/ + exporter, err := otlpmetricgrpc.New(ctx, metricOpts...) + if err != nil { + return nil, errors.WrapIf( + err, + "failed to create otlpmetric exporter for elastic-apm", + ) + } + + elasticApmExporter := metric.NewPeriodicReader( + exporter, + // Default is 1m. Set to 3s for demonstrative purposes. + metric.WithInterval(3*time.Second)) + + exporters = append(exporters, elasticApmExporter) + } + + if o.config.UptraceExporterOptions != nil { + // https://github.com/uptrace/uptrace-go/blob/master/example/otlp-traces/main.go#L49C1-L56C5 + // https://uptrace.dev/get/opentelemetry-go.html#exporting-traces + // https://uptrace.dev/get/opentelemetry-go.html#exporting-metrics + metricOpts = append( + metricOpts, + otlpmetricgrpc.WithEndpoint( + o.config.UptraceExporterOptions.OTLPEndpoint, + ), + otlpmetricgrpc.WithHeaders( + o.config.UptraceExporterOptions.OTLPHeaders, + ), + ) + + // send otel traces to jaeger builtin collector endpoint (default grpc port: 4317) + // https://opentelemetry.io/docs/collector/ + exporter, err := otlpmetricgrpc.New(ctx, metricOpts...) + if err != nil { + return nil, errors.WrapIf( + err, + "failed to create otlpmetric exporter for uptrace", + ) + } + + uptraceExporter := metric.NewPeriodicReader( + exporter, + // Default is 1m. Set to 3s for demonstrative purposes. + metric.WithInterval(3*time.Second)) + + exporters = append(exporters, uptraceExporter) + } + + // https://prometheus.io/docs/prometheus/latest/getting_started/ + // https://prometheus.io/docs/guides/go-application/ + // prometheus exporter will collect otel metrics in prometheus registry + // all prometheus exporters will add to a singleton `prometheus.DefaultRegisterer` registry in newConfig method and this registry will use via `promhttp.Handler` through http endpoint on `/metrics` and calls `Collect` on prometheus Reader interface inner signature prometheus.DefaultRegisterer + prometheusExporter, err := prometheus.New() + if err != nil { + return nil, errors.WrapIf( + err, + "error creating prometheus exporter", + ) + } - return err + exporters = append(exporters, prometheusExporter) + } else { + for _, oltpProvider := range o.config.OTLPProviders { + if !oltpProvider.Enabled { + continue + } + + metricOpts = append(metricOpts, otlpmetricgrpc.WithEndpoint(oltpProvider.OTLPEndpoint), otlpmetricgrpc.WithHeaders(oltpProvider.OTLPHeaders)) + + // send otel metrics to an otel collector endpoint (default grpc port: 4317) + // https://opentelemetry.io/docs/collector/ + // https://github.com/uptrace/uptrace-go/blob/master/example/otlp-metrics/main.go#L28 + // https://github.com/open-telemetry/opentelemetry-go/blob/main/exporters/otlp/otlpmetric/otlpmetricgrpc/example_test.go + exporter, err := otlpmetricgrpc.New(ctx, metricOpts...) + if err != nil { + return nil, errors.WrapIf(err, "failed to create otlptracegrpc exporter") + } + metricExporter := metric.NewPeriodicReader( + exporter, + // Default is 1m. Set to 3s for demonstrative purposes. + metric.WithInterval(3*time.Second)) + + exporters = append(exporters, metricExporter) + } + } + + return exporters, nil } -func (o *OtelMetrics) GracefulShutdown(ctx context.Context) error { - err := o.Echo.Shutdown(ctx) - if err != nil { - return err +// we could also use our existing server app port and a new /metrics endpoint instead of a new server with different port for our app metrics + +func (o *OtelMetrics) RegisterMetricsEndpoint( + server contracts.EchoHttpServer, +) { + if o.config.UseOTLP { + return + } + + var metricsPath string + if o.config.MetricsRoutePath == "" { + metricsPath = "metrics" + } else { + metricsPath = o.config.MetricsRoutePath } - return nil + // when we send request to /metrics endpoint, this handler gets singleton `prometheus.DefaultRegisterer` registry with calling `Collect` method on registered prometheus reader and get all get metrics and write them in /metrics endpoint output + server.GetEchoInstance(). + GET(metricsPath, echo.WrapHandler(promhttp.Handler())) } diff --git a/internal/pkg/otel/metrics/metrics_fx.go b/internal/pkg/otel/metrics/metrics_fx.go new file mode 100644 index 00000000..903059ca --- /dev/null +++ b/internal/pkg/otel/metrics/metrics_fx.go @@ -0,0 +1,92 @@ +package metrics + +import ( + "context" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + + "go.opentelemetry.io/contrib/instrumentation/host" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/metric" + "go.uber.org/fx" +) + +var ( + // Module provided to fxlog + // https://uber-go.github.io/fx/modules.html + Module = fx.Module( //nolint:gochecknoglobals + "otelmetrixfx", + metricsProviders, + metricsInvokes, + ) + + metricsProviders = fx.Options(fx.Provide( //nolint:gochecknoglobals + ProvideMetricsConfig, + NewOtelMetrics, + fx.Annotate( + provideMeter, + fx.ParamTags(`optional:"true"`), + fx.As(new(AppMetrics)), + fx.As(new(metric.Meter))), + )) + + metricsInvokes = fx.Options( //nolint:gochecknoglobals + fx.Invoke(registerHooks), + fx.Invoke(func(m *OtelMetrics, server contracts.EchoHttpServer) { + m.RegisterMetricsEndpoint(server) + }), + ) +) + +func provideMeter(otelMetrics *OtelMetrics) AppMetrics { + return otelMetrics.appMetrics +} + +// we don't want to register any dependencies here, its func body should execute always even we don't request for that, so we should use `invoke` +func registerHooks( + lc fx.Lifecycle, + metrics *OtelMetrics, + logger logger.Logger, +) { + lc.Append(fx.Hook{ + OnStart: func(ctx context.Context) error { + if metrics.appMetrics == nil { + return nil + } + + if metrics.config.EnableHostMetrics { + // https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/instrumentation/host + // we changed default meter provider in metrics setup + logger.Info("Starting host instrumentation:") + err := host.Start( + host.WithMeterProvider(otel.GetMeterProvider()), + ) + if err != nil { + logger.Errorf( + "error starting host instrumentation: %s", + err, + ) + } + } + + return nil + }, + OnStop: func(ctx context.Context) error { + if metrics.appMetrics == nil { + return nil + } + + if err := metrics.Shutdown(ctx); err != nil { + logger.Errorf( + "error in shutting down metrics provider: %v", + err, + ) + } else { + logger.Info("metrics provider shutdown gracefully") + } + + return nil + }, + }) +} diff --git a/internal/pkg/otel/metrics/metrics_options.go b/internal/pkg/otel/metrics/metrics_options.go new file mode 100644 index 00000000..9c8d0977 --- /dev/null +++ b/internal/pkg/otel/metrics/metrics_options.go @@ -0,0 +1,41 @@ +package metrics + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + + "github.com/iancoleman/strcase" +) + +type OTLPProvider struct { + Name string `mapstructure:"name"` + Enabled bool `mapstructure:"enabled"` + OTLPEndpoint string `mapstructure:"otlpEndpoint"` + OTLPHeaders map[string]string `mapstructure:"otlpHeaders"` +} + +type MetricsOptions struct { + Host string `mapstructure:"host"` + Port string `mapstructure:"port"` + ServiceName string `mapstructure:"serviceName"` + Version string `mapstructure:"version"` + MetricsRoutePath string `mapstructure:"metricsRoutePath"` + EnableHostMetrics bool `mapstructure:"enableHostMetrics"` + UseStdout bool `mapstructure:"useStdout"` + InstrumentationName string `mapstructure:"instrumentationName"` + UseOTLP bool `mapstructure:"useOTLP"` + OTLPProviders []OTLPProvider `mapstructure:"otlpProviders"` + ElasticApmExporterOptions *OTLPProvider `mapstructure:"elasticApmExporterOptions"` + UptraceExporterOptions *OTLPProvider `mapstructure:"uptraceExporterOptions"` +} + +func ProvideMetricsConfig( + environment environemnt.Environment, +) (*MetricsOptions, error) { + optionName := strcase.ToLowerCamel( + typeMapper.GetTypeNameByT[MetricsOptions](), + ) + + return config.BindConfigKey[*MetricsOptions](optionName, environment) +} diff --git a/internal/pkg/otel/metrics/metrics_test.go b/internal/pkg/otel/metrics/metrics_test.go new file mode 100644 index 00000000..c4b7e21f --- /dev/null +++ b/internal/pkg/otel/metrics/metrics_test.go @@ -0,0 +1,69 @@ +package metrics_test + +import ( + "fmt" + "io" + "net/http" + "testing" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" + + "go.uber.org/fx" + "go.uber.org/fx/fxtest" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestHealth(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecs(t, "/health suite") +} + +var _ = Describe("/", Ordered, func() { + var ( + url string + err error + res *http.Response + ) + + BeforeAll(func() { + var cfg *metrics.MetricsOptions + + fxtest.New( + GinkgoT(), + zap.Module, + fxlog.FxLogger, + config.Module, + customEcho.Module, + + metrics.Module, + + fx.Populate(&cfg), + ).RequireStart() + + url = fmt.Sprintf("http://%s:%s/metrics", cfg.Host, cfg.Port) + }) + + BeforeEach(func() { + res, err = http.Get(url) + }) + It("returns status OK", func() { + Expect(err).To(BeNil()) + Expect(res.StatusCode).To(Equal(http.StatusOK)) + }) + + It("returns how many requests were made", func() { + b, err := io.ReadAll(res.Body) + Expect(err).To(BeNil()) + + Expect( + b, + ).To(ContainSubstring(`promhttp_metric_handler_requests_total{code="200"} 1`)) + }) +}) diff --git a/internal/pkg/otel/otel_fx.go b/internal/pkg/otel/otel_fx.go deleted file mode 100644 index 52b2295c..00000000 --- a/internal/pkg/otel/otel_fx.go +++ /dev/null @@ -1,107 +0,0 @@ -package otel - -import ( - "context" - "net/http" - - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - - "emperror.dev/errors" - "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/trace" - "go.uber.org/fx" -) - -var ( - // Module provided to fxlog - // https://uber-go.github.io/fx/modules.html - Module = fx.Module( //nolint:gochecknoglobals - "otelfx", - otelProviders, - otelInvokes, - ) - - otelProviders = fx.Options(fx.Provide( //nolint:gochecknoglobals - config.ProvideOtelConfig, - metrics.NewOtelMetrics, - tracing.NewOtelTracing, - fx.Annotate( - provideMeter, - fx.As(new(metric.Meter))), - fx.Annotate( - provideTracer, - fx.As(new(tracing.AppTracer)), - fx.As(new(trace.Tracer)), - ), - )) - - otelInvokes = fx.Options(fx.Invoke(registerHooks)) //nolint:gochecknoglobals -) - -func provideMeter(otelMetrics *metrics.OtelMetrics) metric.Meter { - return otelMetrics.Meter -} - -func provideTracer(tracingOtel *tracing.TracingOpenTelemetry) tracing.AppTracer { - return tracingOtel.AppTracer -} - -// we don't want to register any dependencies here, its func body should execute always even we don't request for that, so we should use `invoke` -func registerHooks( - lc fx.Lifecycle, - metrics *metrics.OtelMetrics, - logger logger.Logger, - tracingOtel *tracing.TracingOpenTelemetry, -) { - lc.Append(fx.Hook{ - OnStart: func(ctx context.Context) error { - if metrics.Meter == nil { - return nil - } - - go func() { - // https://medium.com/@mokiat/proper-http-shutdown-in-go-bd3bfaade0f2 - // When Shutdown is called, Serve, ListenAndServe, and ListenAndServeTLS immediately return ErrServerClosed. Make sure the program doesn’t exit and waits instead for Shutdown to return. - if err := metrics.Run(); !errors.Is(err, http.ErrServerClosed) { - // do a fatal for running OnStop hook - logger.Fatalf( - "(metrics.RunHttpServer) error in running metrics server: {%v}", - err, - ) - } - }() - logger.Infof( - "Metrics server %s is listening on Host:{%s} Http PORT: {%s}", - metrics.Config.OTelMetricsOptions.Name, - metrics.Config.OTelMetricsOptions.Host, - metrics.Config.OTelMetricsOptions.Port, - ) - - return nil - }, - OnStop: func(ctx context.Context) error { - if err := tracingOtel.TracerProvider.Shutdown(ctx); err != nil { - logger.Errorf("error in shutting down trace provider: %v", err) - } else { - logger.Info("trace provider shutdown gracefully") - } - - if metrics.Meter == nil { - return nil - } - // https://github.com/uber-go/fx/blob/v1.20.0/app.go#L573 - // this ctx is just for stopping callbacks or OnStop callbacks, and it has short timeout 15s, and it is not alive in whole lifetime app - // https://medium.com/@mokiat/proper-http-shutdown-in-go-bd3bfaade0f2 - // When Shutdown is called, Serve, ListenAndServe, and ListenAndServeTLS immediately return ErrServerClosed. Make sure the program doesn’t exit and waits instead for Shutdown to return. - if err := metrics.GracefulShutdown(ctx); err != nil { - logger.Errorf("error shutting down metrics server: %v", err) - } else { - logger.Info("metrics server shutdown gracefully") - } - return nil - }, - }) -} diff --git a/internal/pkg/otel/tracing/tracing.go b/internal/pkg/otel/tracing/tracing.go index 8dc8c569..c216f6cc 100644 --- a/internal/pkg/otel/tracing/tracing.go +++ b/internal/pkg/otel/tracing/tracing.go @@ -1,15 +1,25 @@ package tracing +// https://opentelemetry.io/docs/reference/specification/ +// https://opentelemetry.io/docs/instrumentation/go/getting-started/ +// https://opentelemetry.io/docs/instrumentation/go/manual/ +// https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/ +// https://uptrace.dev/opentelemetry/go-tracing.html +// https://lightstep.com/blog/opentelemetry-go-all-you-need-to-know +// https://trstringer.com/otel-part2-instrumentation/ +// https://trstringer.com/otel-part5-propagation/ +// https://github.com/tedsuo/otel-go-basics/blob/main/server.go +// https://github.com/riferrei/otel-with-golang/blob/main/main.go + import ( "context" - "fmt" "os" "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" - config2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/config" "emperror.dev/errors" + "github.com/samber/lo" "go.opentelemetry.io/contrib/propagators/ot" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" @@ -20,77 +30,74 @@ import ( "go.opentelemetry.io/otel/sdk/resource" tracesdk "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.21.0" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - - _ "go.opentelemetry.io/otel" ) -// https://opentelemetry.io/docs/reference/specification/ -// https://opentelemetry.io/docs/instrumentation/go/getting-started/ -// https://opentelemetry.io/docs/instrumentation/go/manual/ -// https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/ -// https://uptrace.dev/opentelemetry/go-tracing.html -// https://lightstep.com/blog/opentelemetry-go-all-you-need-to-know -// https://trstringer.com/otel-part2-instrumentation/ -// https://trstringer.com/otel-part5-propagation/ -// https://github.com/tedsuo/otel-go-basics/blob/main/server.go - type TracingOpenTelemetry struct { - config *config2.OpenTelemetryOptions - jaegerExporter tracesdk.SpanExporter - zipkinExporter tracesdk.SpanExporter - stdExporter tracesdk.SpanExporter - environment environemnt.Environment - TracerProvider *tracesdk.TracerProvider - AppTracer AppTracer + config *TracingOptions + environment environemnt.Environment + appTracer AppTracer + provider *tracesdk.TracerProvider } // Create one tracer per package // NOTE: You only need a tracer if you are creating your own spans func NewOtelTracing( - config *config2.OpenTelemetryOptions, + config *TracingOptions, environment environemnt.Environment, ) (*TracingOpenTelemetry, error) { - openTel := &TracingOpenTelemetry{config: config, environment: environment} + otelTracing := &TracingOpenTelemetry{ + config: config, + environment: environment, + } - err := openTel.configExporters() + resource, err := otelTracing.newResource() if err != nil { - return nil, errors.WrapIf(err, "error in config exporter") + return nil, errors.WrapIf(err, "failed to create resource") } - // https://opentelemetry.io/docs/instrumentation/go/manual/#initializing-a-new-tracer - err = openTel.configTracerProvider() + appTracer, err := otelTracing.initTracer(resource) if err != nil { return nil, err } - // https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/propagators/ot/ot_propagator.go - // https://github.com/open-telemetry/opentelemetry-go/blob/main/propagation/trace_context.go - // https://github.com/open-telemetry/opentelemetry-go/blob/main/propagation/baggage.go/ - // https://trstringer.com/otel-part5-propagation/ - propagators := []propagation.TextMapPropagator{ - ot.OT{}, // should be placed before `TraceContext` for preventing conflict - propagation.TraceContext{}, - propagation.Baggage{}, - } + otelTracing.appTracer = appTracer - // Register our TracerProvider as the global so any imported - // instrumentation in the future will default to using it. - otel.SetTracerProvider(openTel.TracerProvider) - otel.SetTextMapPropagator( - propagation.NewCompositeTextMapPropagator(propagators...), - ) + return otelTracing, nil +} - // https://trstringer.com/otel-part2-instrumentation/ - // Finally, set the tracer that can be used for this package. global app tracer - openTel.AppTracer = NewAppTracer(config.InstrumentationName) +func (o *TracingOpenTelemetry) Shutdown(ctx context.Context) error { + return o.provider.Shutdown(ctx) +} + +func (o *TracingOpenTelemetry) newResource() (*resource.Resource, error) { + // https://github.com/uptrace/uptrace-go/blob/master/example/otlp-traces/main.go#L49C1-L56C5 + resource, err := resource.New(context.Background(), + resource.WithFromEnv(), + resource.WithTelemetrySDK(), + resource.WithHost(), + resource.WithOS(), + resource.WithSchemaURL(semconv.SchemaURL), + resource.WithAttributes( + semconv.ServiceName(o.config.ServiceName), + semconv.ServiceVersion(o.config.Version), + attribute.Int64("ID", o.config.Id), + attribute.String("environment", o.environment.GetEnvironmentName()), + semconv.TelemetrySDKVersionKey.String("v1.21.0"), // semconv version + semconv.TelemetrySDKLanguageGo, + )) - return openTel, nil + return resource, err } -func (o *TracingOpenTelemetry) configTracerProvider() error { +func (o *TracingOpenTelemetry) initTracer( + resource *resource.Resource, +) (AppTracer, error) { + exporters, err := o.configExporters() + if err != nil { + return nil, err + } + var sampler tracesdk.Sampler if o.config.AlwaysOnSampler { sampler = tracesdk.AlwaysSample() @@ -98,95 +105,192 @@ func (o *TracingOpenTelemetry) configTracerProvider() error { sampler = tracesdk.NeverSample() } - // https://github.com/open-telemetry/opentelemetry-go/blob/main/example/fib/main.go#L44 - // Ensure default SDK resources and the required service name are set. - r, err := resource.Merge( - resource.Default(), - resource.NewWithAttributes( - semconv.SchemaURL, - semconv.ServiceNameKey.String(o.config.ServiceName), - attribute.Int64("ID", o.config.Id), - attribute.String("environment", o.environment.GetEnvironmentName()), - ), + batchExporters := lo.Map( + exporters, + func(item tracesdk.SpanExporter, index int) tracesdk.TracerProviderOption { + return tracesdk.WithBatcher(item) + }, ) - if err != nil { - return err - } - tp := tracesdk.NewTracerProvider( - // Always be sure to batch in production. - tracesdk.WithBatcher(o.jaegerExporter), - tracesdk.WithBatcher(o.zipkinExporter), - tracesdk.WithBatcher(o.stdExporter), + // https://opentelemetry.io/docs/instrumentation/go/exporting_data/#resources + // Resources are a special type of attribute that apply to all spans generated by a process + opts := append( + batchExporters, + tracesdk.WithResource(resource), tracesdk.WithSampler(sampler), + ) + + provider := tracesdk.NewTracerProvider(opts...) - // https://opentelemetry.io/docs/instrumentation/go/exporting_data/#resources - // Resources are a special type of attribute that apply to all spans generated by a process - tracesdk.WithResource(r), + // Register our TracerProvider as the global so any imported + // instrumentation in the future will default to using it. + otel.SetTracerProvider(provider) + o.provider = provider + + // https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/propagators/ot/ot_propagator.go + // https://github.com/open-telemetry/opentelemetry-go/blob/main/propagation/trace_context.go + // https://github.com/open-telemetry/opentelemetry-go/blob/main/propagation/baggage.go/ + // https://trstringer.com/otel-part5-propagation/ + otel.SetTextMapPropagator( + propagation.NewCompositeTextMapPropagator( + ot.OT{}, // should be placed before `TraceContext` for preventing conflict + propagation.Baggage{}, + propagation.TraceContext{}, + ), ) - o.TracerProvider = tp - return nil + + // https://trstringer.com/otel-part2-instrumentation/ + // Finally, set the tracer that can be used for this package. global app tracer + appTracer := NewAppTracer(o.config.InstrumentationName) + + return appTracer, nil } -func (o *TracingOpenTelemetry) configExporters() error { - if o.config.JaegerExporterOptions != nil { +func (o *TracingOpenTelemetry) configExporters() ([]tracesdk.SpanExporter, error) { + ctx := context.Background() + traceOpts := []otlptracegrpc.Option{ + otlptracegrpc.WithTimeout(5 * time.Second), + otlptracegrpc.WithInsecure(), + } + + var exporters []tracesdk.SpanExporter + + if !o.config.UseOTLP { //nolint:nestif + // jaeger exporter removed from otel spec (it used jaeger agent and jaeger agent port), now we should use OTLP which supports by jaeger now by its built-in `collector` + // https://medium.com/jaegertracing/introducing-native-support-for-opentelemetry-in-jaeger-eb661be8183c // https://www.jaegertracing.io/docs/1.38/apis/#opentelemetry-protocol-stable // https://deploy-preview-1892--opentelemetry.netlify.app/blog/2022/jaeger-native-otlp/ // https://www.jaegertracing.io/docs/1.49/getting-started/ // https://opentelemetry.io/docs/instrumentation/go/exporters/ // https://opentelemetry.io/docs/specs/otlp/ // https://github.com/open-telemetry/opentelemetry-go/pull/4467 - ctx, cancel := context.WithTimeout(context.Background(), time.Second) - defer cancel() - - conn, err := grpc.DialContext( - ctx, - o.config.JaegerExporterOptions.OtlpEndpoint, // default OTLP endpoint address is `localhost:4317` - // Note the use of insecure transport here. TLS is recommended in production. - grpc.WithTransportCredentials(insecure.NewCredentials()), - grpc.WithBlock(), - ) - if err != nil { - return fmt.Errorf( - "failed to create gRPC connection to collector: %w", - err, + if o.config.JaegerExporterOptions != nil { + traceOpts = append( + traceOpts, + otlptracegrpc.WithEndpoint( + o.config.JaegerExporterOptions.OTLPEndpoint, + ), + otlptracegrpc.WithHeaders( + o.config.JaegerExporterOptions.OTLPHeaders, + ), ) + + // send otel traces to jaeger builtin collector endpoint (default grpc port: 4317) + // https://opentelemetry.io/docs/collector/ + jaegerTraceExporter, err := otlptracegrpc.New(ctx, traceOpts...) + if err != nil { + return nil, errors.WrapIf( + err, + "failed to create oltptrace exporter for jaeger", + ) + } + + exporters = append(exporters, jaegerTraceExporter) } - // Set up a trace exporter - jaegerTraceExporter, err := otlptracegrpc.New( - ctx, - otlptracegrpc.WithGRPCConn(conn), - ) - if err != nil { - return fmt.Errorf("failed to create trace exporter: %w", err) + if o.config.ZipkinExporterOptions != nil { + zipkinExporter, err := zipkin.New( + o.config.ZipkinExporterOptions.Url, + ) + if err != nil { + return nil, errors.WrapIf( + err, + "failed to create exporter for zipkin", + ) + } + + exporters = append(exporters, zipkinExporter) } - o.jaegerExporter = jaegerTraceExporter - } - if o.config.ZipkinExporterOptions != nil { - zipkinExporter, err := zipkin.New( - o.config.ZipkinExporterOptions.Url, - ) - if err != nil { - return err + if o.config.ElasticApmExporterOptions != nil { + // https://www.elastic.co/guide/en/apm/guide/current/open-telemetry.html + // https://www.elastic.co/guide/en/apm/guide/current/open-telemetry-direct.html#instrument-apps-otel + // https://github.com/anilsenay/go-opentelemetry-examples/blob/elastic/cmd/main.go#L35 + traceOpts = append( + traceOpts, + otlptracegrpc.WithEndpoint( + o.config.ElasticApmExporterOptions.OTLPEndpoint, + ), + otlptracegrpc.WithHeaders( + o.config.ElasticApmExporterOptions.OTLPHeaders, + ), + ) + + // send otel traces to jaeger builtin collector endpoint (default grpc port: 4317) + // https://opentelemetry.io/docs/collector/ + elasticApmExporter, err := otlptracegrpc.New(ctx, traceOpts...) + if err != nil { + return nil, errors.WrapIf( + err, + "failed to create oltptrace exporter for elastic-apm", + ) + } + + exporters = append(exporters, elasticApmExporter) } - o.zipkinExporter = zipkinExporter - } - if o.config.UseStdout { - stdExporter, err := stdouttrace.New( - stdouttrace.WithWriter( - os.Stdout, - ), // stdExporter default is `stdouttrace.WithWriter(os.Stdout)`, we can remove this also - stdouttrace.WithPrettyPrint(), // make output json with pretty printing - ) - if err != nil { - return fmt.Errorf("creating stdout exporter: %w", err) + if o.config.UptraceExporterOptions != nil { + // https://github.com/uptrace/uptrace-go/blob/master/example/otlp-traces/main.go#L49C1-L56C5 + // https://uptrace.dev/get/opentelemetry-go.html#exporting-traces + // https://uptrace.dev/get/opentelemetry-go.html#exporting-metrics + traceOpts = append( + traceOpts, + otlptracegrpc.WithEndpoint( + o.config.UptraceExporterOptions.OTLPEndpoint, + ), + otlptracegrpc.WithHeaders( + o.config.UptraceExporterOptions.OTLPHeaders, + ), + ) + + // send otel traces to jaeger builtin collector endpoint (default grpc port: 4317) + // https://opentelemetry.io/docs/collector/ + uptraceExporter, err := otlptracegrpc.New(ctx, traceOpts...) + if err != nil { + return nil, errors.WrapIf( + err, + "failed to create oltptrace exporter for uptrace", + ) + } + + exporters = append(exporters, uptraceExporter) + } + + if o.config.UseStdout { + stdExporter, err := stdouttrace.New( + stdouttrace.WithWriter( + os.Stdout, + ), // stdExporter default is `stdouttrace.WithWriter(os.Stdout)`, we can remove this also + stdouttrace.WithPrettyPrint(), // make output json with pretty printing + ) + if err != nil { + return nil, errors.WrapIf(err, "creating stdout exporter") + } + + exporters = append(exporters, stdExporter) + } + } else { + // use some otel collector endpoints + for _, oltpProvider := range o.config.OTLPProviders { + if !oltpProvider.Enabled { + continue + } + + traceOpts = append(traceOpts, otlptracegrpc.WithEndpoint(oltpProvider.OTLPEndpoint), otlptracegrpc.WithHeaders(oltpProvider.OTLPHeaders)) + + // send otel metrics to an otel collector endpoint (default grpc port: 4317) + // https://opentelemetry.io/docs/collector/ + // https://github.com/uptrace/uptrace-go/blob/master/example/otlp-traces/main.go#L29 + // https://github.com/open-telemetry/opentelemetry-go/blob/main/exporters/otlp/otlptrace/otlptracehttp/example_test.go#L70 + traceExporter, err := otlptracegrpc.New(ctx, traceOpts...) + if err != nil { + return nil, errors.WrapIf(err, "failed to create otlptracegrpc exporter") + } + + exporters = append(exporters, traceExporter) } - o.stdExporter = stdExporter } - return nil + return exporters, nil } diff --git a/internal/pkg/otel/tracing/tracing_fx.go b/internal/pkg/otel/tracing/tracing_fx.go new file mode 100644 index 00000000..fdaf9bb6 --- /dev/null +++ b/internal/pkg/otel/tracing/tracing_fx.go @@ -0,0 +1,60 @@ +package tracing + +import ( + "context" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + + "go.opentelemetry.io/otel/trace" + "go.uber.org/fx" +) + +var ( + // Module provided to fxlog + // https://uber-go.github.io/fx/modules.html + Module = fx.Module( //nolint:gochecknoglobals + "oteltracingfx", + tracingProviders, + tracingInvokes, + ) + + tracingProviders = fx.Options(fx.Provide( //nolint:gochecknoglobals + ProvideTracingConfig, + NewOtelTracing, + fx.Annotate( + provideTracer, + fx.ParamTags(`optional:"true"`), + fx.As(new(AppTracer)), + fx.As(new(trace.Tracer)), + ), + )) + + tracingInvokes = fx.Options( + fx.Invoke(registerHooks), + ) //nolint:gochecknoglobals +) + +func provideTracer( + tracingOtel *TracingOpenTelemetry, +) AppTracer { + return tracingOtel.appTracer +} + +// we don't want to register any dependencies here, its func body should execute always even we don't request for that, so we should use `invoke` +func registerHooks( + lc fx.Lifecycle, + logger logger.Logger, + tracingOtel *TracingOpenTelemetry, +) { + lc.Append(fx.Hook{ + OnStop: func(ctx context.Context) error { + if err := tracingOtel.Shutdown(ctx); err != nil { + logger.Errorf("error in shutting down trace provider: %v", err) + } else { + logger.Info("trace provider shutdown gracefully") + } + + return nil + }, + }) +} diff --git a/internal/pkg/otel/tracing/tracing_options.go b/internal/pkg/otel/tracing/tracing_options.go new file mode 100644 index 00000000..04259c73 --- /dev/null +++ b/internal/pkg/otel/tracing/tracing_options.go @@ -0,0 +1,46 @@ +package tracing + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + + "github.com/iancoleman/strcase" +) + +type OTLPProvider struct { + Name string `mapstructure:"name"` + Enabled bool `mapstructure:"enabled"` + OTLPEndpoint string `mapstructure:"otlpEndpoint"` + OTLPHeaders map[string]string `mapstructure:"otlpHeaders"` +} + +type TracingOptions struct { + Enabled bool `mapstructure:"enabled"` + ServiceName string `mapstructure:"serviceName"` + Version string `mapstructure:"version"` + InstrumentationName string `mapstructure:"instrumentationName"` + Id int64 `mapstructure:"id"` + AlwaysOnSampler bool `mapstructure:"alwaysOnSampler"` + ZipkinExporterOptions *ZipkinExporterOptions `mapstructure:"zipkinExporterOptions"` + JaegerExporterOptions *OTLPProvider `mapstructure:"jaegerExporterOptions"` + ElasticApmExporterOptions *OTLPProvider `mapstructure:"elasticApmExporterOptions"` + UptraceExporterOptions *OTLPProvider `mapstructure:"uptraceExporterOptions"` + UseStdout bool `mapstructure:"useStdout"` + UseOTLP bool `mapstructure:"useOTLP"` + OTLPProviders []OTLPProvider `mapstructure:"otlpProviders"` +} + +type ZipkinExporterOptions struct { + Url string `mapstructure:"url"` +} + +func ProvideTracingConfig( + environment environemnt.Environment, +) (*TracingOptions, error) { + optionName := strcase.ToLowerCamel( + typeMapper.GetTypeNameByT[TracingOptions](), + ) + + return config.BindConfigKey[*TracingOptions](optionName, environment) +} diff --git a/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go b/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go index afeffa1e..6d4f0ad8 100644 --- a/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go +++ b/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go @@ -12,7 +12,6 @@ import ( messageConsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/pipeline" types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" - config2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" @@ -34,15 +33,15 @@ func Test_Consume_Message(t *testing.T) { defaultLogger2.SetupDefaultLogger() eventSerializer := serializer.NewDefaultEventSerializer(json.NewDefaultSerializer()) - tp, err := tracing.NewOtelTracing(&config2.OpenTelemetryOptions{ + tp, err := tracing.NewOtelTracing(&tracing.TracingOptions{ ServiceName: "test", Enabled: true, AlwaysOnSampler: true, - JaegerExporterOptions: &config2.JaegerExporterOptions{ + JaegerExporterOptions: &tracing.JaegerExporterOptions{ AgentHost: "localhost", AgentPort: "6831", }, - ZipkinExporterOptions: &config2.ZipkinExporterOptions{ + ZipkinExporterOptions: &tracing.ZipkinExporterOptions{ Url: "http://localhost:9411/api/v2/spans", }, }, environemnt.Development) diff --git a/internal/pkg/rabbitmq/health.go b/internal/pkg/rabbitmq/health.go index 9650ad34..f5289f14 100644 --- a/internal/pkg/rabbitmq/health.go +++ b/internal/pkg/rabbitmq/health.go @@ -3,7 +3,7 @@ package rabbitmq import ( "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" "emperror.dev/errors" @@ -13,7 +13,7 @@ type gormHealthChecker struct { connection types.IConnection } -func NewRabbitMQHealthChecker(connection types.IConnection) health.Health { +func NewRabbitMQHealthChecker(connection types.IConnection) contracts.Health { return &gormHealthChecker{connection} } diff --git a/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go b/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go index 22d89d6f..1c0dcf30 100644 --- a/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go +++ b/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go @@ -9,7 +9,6 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/json" defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" - config2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" @@ -27,11 +26,11 @@ func Test_Publish_Message(t *testing.T) { ctx := context.Background() tp, err := tracing.NewOtelTracing( - &config2.OpenTelemetryOptions{ + &tracing.TracingOptions{ ServiceName: "test", Enabled: true, AlwaysOnSampler: true, - JaegerExporterOptions: &config2.JaegerExporterOptions{ + JaegerExporterOptions: &tracing.JaegerExporterOptions{ AgentHost: "localhost", AgentPort: "6831", }, diff --git a/internal/pkg/rabbitmq/rabbitmq_fx.go b/internal/pkg/rabbitmq/rabbitmq_fx.go index d601b5eb..4ad35003 100644 --- a/internal/pkg/rabbitmq/rabbitmq_fx.go +++ b/internal/pkg/rabbitmq/rabbitmq_fx.go @@ -5,7 +5,7 @@ import ( "fmt" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" bus2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/bus" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" @@ -44,7 +44,7 @@ var ( )), fx.Provide(fx.Annotate( NewRabbitMQHealthChecker, - fx.As(new(health.Health)), + fx.As(new(contracts.Health)), fx.ResultTags(fmt.Sprintf(`group:"%s"`, "healths")), ))) diff --git a/internal/pkg/redis/health.go b/internal/pkg/redis/health.go index 8ab22b02..b5c25b50 100644 --- a/internal/pkg/redis/health.go +++ b/internal/pkg/redis/health.go @@ -3,7 +3,7 @@ package redis import ( "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health/contracts" "github.com/redis/go-redis/v9" ) @@ -12,7 +12,7 @@ type RedisHealthChecker struct { client *redis.Client } -func NewRedisHealthChecker(client *redis.Client) health.Health { +func NewRedisHealthChecker(client *redis.Client) contracts.Health { return &RedisHealthChecker{client} } diff --git a/internal/pkg/redis/redis.go b/internal/pkg/redis/redis.go index 742c104d..46d9569d 100644 --- a/internal/pkg/redis/redis.go +++ b/internal/pkg/redis/redis.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + "github.com/redis/go-redis/extra/redisotel/v9" "github.com/redis/go-redis/v9" ) @@ -34,5 +35,9 @@ func NewRedisClient(cfg *RedisOptions) *redis.Client { PoolTimeout: poolTimeout, }) + if cfg.EnableTracing { + _ = redisotel.InstrumentTracing(universalClient) + } + return universalClient } diff --git a/internal/pkg/redis/redis_fx.go b/internal/pkg/redis/redis_fx.go index 266bf24f..02d5f341 100644 --- a/internal/pkg/redis/redis_fx.go +++ b/internal/pkg/redis/redis_fx.go @@ -4,10 +4,9 @@ import ( "context" "fmt" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/redis/go-redis/extra/redisotel/v9" "github.com/redis/go-redis/v9" "go.uber.org/fx" ) @@ -15,7 +14,11 @@ import ( var ( // Module provided to fxlog // https://uber-go.github.io/fx/modules.html - Module = fx.Module("redisfx", redisProviders, redisInvokes) //nolint:gochecknoglobals + Module = fx.Module( + "redisfx", + redisProviders, + redisInvokes, + ) //nolint:gochecknoglobals redisProviders = fx.Options(fx.Provide( //nolint:gochecknoglobals NewRedisClient, @@ -29,16 +32,21 @@ var ( //), fx.Annotate( NewRedisHealthChecker, - fx.As(new(health.Health)), + fx.As(new(contracts.Health)), fx.ResultTags(fmt.Sprintf(`group:"%s"`, "healths")), ), provideConfig)) - redisInvokes = fx.Options(fx.Invoke(registerHooks), //nolint:gochecknoglobals - fx.Invoke(EnableTracing)) + redisInvokes = fx.Options( + fx.Invoke(registerHooks), + ) //nolint:gochecknoglobals ) -func registerHooks(lc fx.Lifecycle, client redis.UniversalClient, logger logger.Logger) { +func registerHooks( + lc fx.Lifecycle, + client redis.UniversalClient, + logger logger.Logger, +) { lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { return client.Ping(ctx).Err() @@ -54,7 +62,3 @@ func registerHooks(lc fx.Lifecycle, client redis.UniversalClient, logger logger. }, }) } - -func EnableTracing(redis *redis.Client) error { - return redisotel.InstrumentTracing(redis) -} diff --git a/internal/pkg/redis/redis_options.go b/internal/pkg/redis/redis_options.go index 788d828c..5d0fecef 100644 --- a/internal/pkg/redis/redis_options.go +++ b/internal/pkg/redis/redis_options.go @@ -11,11 +11,12 @@ import ( var optionName = strcase.ToLowerCamel(typeMapper.GetTypeNameByT[RedisOptions]()) type RedisOptions struct { - Host string `mapstructure:"host"` - Port int `mapstructure:"port"` - Password string `mapstructure:"password"` - Database int `mapstructure:"database"` - PoolSize int `mapstructure:"poolSize"` + Host string `mapstructure:"host"` + Port int `mapstructure:"port"` + Password string `mapstructure:"password"` + Database int `mapstructure:"database"` + PoolSize int `mapstructure:"poolSize"` + EnableTracing bool `mapstructure:"enableTracing" default:"true"` } func provideConfig(environment environemnt.Environment) (*RedisOptions, error) { diff --git a/internal/services/catalog_read_service/config/config.development.json b/internal/services/catalog_read_service/config/config.development.json index 3c60ef3d..6353dc65 100644 --- a/internal/services/catalog_read_service/config/config.development.json +++ b/internal/services/catalog_read_service/config/config.development.json @@ -55,24 +55,43 @@ "database": "catalogs_service", "useAuth": true }, - "openTelemetryOptions": { + "tracingOptions": { "enable": true, "serviceName": "catalogs-read-service", - "instrumentationName": "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice", + "instrumentationName": "io.opentelemetry.traces.catalogs-read-service", "id": 1, - "alwaysOnSampler": true, "useStdout": false, + "alwaysOnSampler": true, "jaegerExporterOptions": { - "otlpEndpoint": "localhost:4317" + "otlpEndpoint": "localhost:4320", + "enabled": true }, "zipkinExporterOptions": { "url": "http://localhost:9411/api/v2/spans" }, - "otelMetricsOptions": { - "port": ":1003", - "metricsRoutePath": "/metrics", - "name": "catalogs-read-service" - } + "otlpProviders": [ + { + "name": "uptrace", + "enabled": false, + "otlpEndpoint": "otlp.uptrace.dev:4317", + "otlpHeaders": { + "uptrace-dsn": "https://@uptrace.dev/" + } + }, + { + "name": "elastic-apm", + "enabled": false, + "otlpEndpoint": "host.docker.internal:4317", + "otlpHeaders": { + "Authorization": "Bearer ${ELASTIC_APM_SECRET_TOKEN}" + } + } + ] + }, + "metricsOptions": { + "metricsRoutePath": "/metrics", + "serviceName": "catalogs-read-service", + "instrumentationName": "io.opentelemetry.metrics.catalogs-write-service" }, "elasticOptions": { "url": "http://localhost:9200", diff --git a/internal/services/catalog_read_service/config/config.test.json b/internal/services/catalog_read_service/config/config.test.json index 883d8bb9..a0d095ac 100644 --- a/internal/services/catalog_read_service/config/config.test.json +++ b/internal/services/catalog_read_service/config/config.test.json @@ -53,24 +53,43 @@ "database": "catalogs_service", "useAuth": true }, - "openTelemetryOptions": { + "tracingOptions": { "enable": true, "serviceName": "catalogs-read-service", - "instrumentationName": "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice", + "instrumentationName": "io.opentelemetry.traces.catalogs-read-service", "id": 1, - "alwaysOnSampler": true, "useStdout": false, + "alwaysOnSampler": true, "jaegerExporterOptions": { - "otlpEndpoint": "localhost:4317" + "otlpEndpoint": "localhost:4320", + "enabled": true }, "zipkinExporterOptions": { "url": "http://localhost:9411/api/v2/spans" }, - "otelMetricsOptions": { - "port": ":2002", - "metricsRoutePath": "/metrics", - "name": "catalogs-read-service" - } + "otlpProviders": [ + { + "name": "uptrace", + "enabled": false, + "otlpEndpoint": "otlp.uptrace.dev:4317", + "otlpHeaders": { + "uptrace-dsn": "https://@uptrace.dev/" + } + }, + { + "name": "elastic-apm", + "enabled": false, + "otlpEndpoint": "host.docker.internal:4317", + "otlpHeaders": { + "Authorization": "Bearer ${ELASTIC_APM_SECRET_TOKEN}" + } + } + ] + }, + "metricsOptions": { + "metricsRoutePath": "/metrics", + "serviceName": "catalogs-read-service", + "instrumentationName": "io.opentelemetry.metrics.catalogs-write-service" }, "elasticOptions": { "url": "http://localhost:9200", diff --git a/internal/services/catalog_read_service/go.mod b/internal/services/catalog_read_service/go.mod index b91826fd..dd54f172 100644 --- a/internal/services/catalog_read_service/go.mod +++ b/internal/services/catalog_read_service/go.mod @@ -40,7 +40,7 @@ require ( github.com/KyleBanks/depth v1.2.1 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/Microsoft/hcsshim v0.11.0 // indirect + github.com/Microsoft/hcsshim v0.11.1 // indirect github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 // indirect github.com/ahmetb/go-linq/v3 v3.2.0 // indirect github.com/ajg/form v1.5.1 // indirect @@ -143,7 +143,7 @@ require ( github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.11.1 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/rabbitmq/amqp091-go v1.8.1 // indirect github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 // indirect @@ -154,7 +154,7 @@ require ( github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smarty/assertions v1.15.0 // indirect - github.com/spf13/afero v1.9.5 // indirect + github.com/spf13/afero v1.10.0 // indirect github.com/spf13/cast v1.5.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect @@ -168,6 +168,7 @@ require ( github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect github.com/uptrace/bun v1.1.16 // indirect github.com/uptrace/bun/driver/pgdriver v1.1.16 // indirect + github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2 // indirect github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 // indirect github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect @@ -190,10 +191,14 @@ require ( go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 // indirect go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 // indirect + go.opentelemetry.io/contrib/instrumentation/host v0.44.0 // indirect go.opentelemetry.io/contrib/propagators/ot v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 // indirect go.opentelemetry.io/otel/exporters/prometheus v0.41.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 // indirect go.opentelemetry.io/otel/exporters/zipkin v1.18.0 // indirect go.opentelemetry.io/otel/sdk v1.18.0 // indirect @@ -214,7 +219,7 @@ require ( golang.org/x/tools v0.13.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect - google.golang.org/grpc v1.58.1 // indirect + google.golang.org/grpc v1.58.2 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/internal/services/catalog_read_service/go.sum b/internal/services/catalog_read_service/go.sum index 97b57c7b..f8aa2c38 100644 --- a/internal/services/catalog_read_service/go.sum +++ b/internal/services/catalog_read_service/go.sum @@ -83,8 +83,8 @@ github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA4 github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.11.0 h1:7EFNIY4igHEXUdj1zXgAyU3fLc7QfOKHbkldRVTBdiM= -github.com/Microsoft/hcsshim v0.11.0/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= +github.com/Microsoft/hcsshim v0.11.1 h1:hJ3s7GbWlGK4YVV92sO88BQSyF4ZLVy7/awqOlPxFbA= +github.com/Microsoft/hcsshim v0.11.1/go.mod h1:nFJmaO4Zr5Y7eADdFOpYswDDlNVbvcIJJNJLECr5JQg= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4= @@ -240,6 +240,8 @@ github.com/go-playground/validator v9.31.0+incompatible/go.mod h1:yrEkQXlcI+Pugk github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-reflect v1.2.0 h1:O0T8rZCuNmGXewnATuKYnkL0xm6o8UNOJZd/gOkb9ms= @@ -323,6 +325,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 h1:gpptm606MZYGaMHMsB4Srmb6EbW/IVHnt04rcMXnkBQ= +github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -545,6 +549,8 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.12.1 h1:uHNEO1RP2SpuZApSkel9nEh1/Mu+hmQe7Q+Pepg5OYA= +github.com/onsi/ginkgo/v2 v2.12.1/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -587,8 +593,8 @@ github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUo github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= @@ -649,8 +655,8 @@ github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGB github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY= github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= +github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= @@ -707,6 +713,8 @@ github.com/uptrace/bun v1.1.16 h1:cn9cgEMFwcyYRsQLfxCRMUxyK1WaHwOVrR3TvzEFZ/A= github.com/uptrace/bun v1.1.16/go.mod h1:7HnsMRRvpLFUcquJxp22JO8PsWKpFQO/gNXqqsuGWg8= github.com/uptrace/bun/driver/pgdriver v1.1.16 h1:b/NiSXk6Ldw7KLfMLbOqIkm4odHd7QiNOCPLqPFJjK4= github.com/uptrace/bun/driver/pgdriver v1.1.16/go.mod h1:Rmfbc+7lx1z/umjMyAxkOHK81LgnGj71XC5YpA6k1vU= +github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2 h1:s3quVevwQlgEMCkvscS/VHo92amtyMzRfcuOZqfevrM= +github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2/go.mod h1:IJLBT7ItgUACTEoq6BEw/9HwHWL4BiPirYgKhZS83Lg= github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 h1:CNznWHkrbA6o1q2H/BsH4tIHf4zbKNtndeoV+AH8z0U= github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2/go.mod h1:7YSrHCmYPHIXjTWnKSU7EGT0TFEcm3WwSeQquwCGg38= github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 h1:uyrW06oJi4iWvhjPLVfk4qrSP2Zm0AMozKKDmp6i4pE= @@ -781,18 +789,26 @@ go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/ot go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0/go.mod h1:JH6FxBlkXo/cYoU/m65W5dOQ6sqPL+jHtSJaSE7/+XQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 h1:b8xjZxHbLrXAum4SxJd1Rlm7Y/fKaB+6ACI7/e5EfSA= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0/go.mod h1:1ei0a32xOGkFoySu7y1DAHfcuIhC0pNZpvY2huXuMy4= +go.opentelemetry.io/contrib/instrumentation/host v0.44.0 h1:SNqDjPpQmwFYvDipyJJxDbU5zKNWiYSMii864ubzIuQ= +go.opentelemetry.io/contrib/instrumentation/host v0.44.0/go.mod h1:bZcqg3yy0riQLNkx8dJWV4J3tbfL+6LQ5lIbI+vmarE= go.opentelemetry.io/contrib/propagators/b3 v1.19.0 h1:ulz44cpm6V5oAeg5Aw9HyqGFMS6XM7untlMEhD7YzzA= go.opentelemetry.io/contrib/propagators/b3 v1.19.0/go.mod h1:OzCmE2IVS+asTI+odXQstRGVfXQ4bXv9nMBRK0nNyqQ= go.opentelemetry.io/contrib/propagators/ot v1.19.0 h1:vODRLMlKN4ApM8ri0UDk8nnEeISuwxpf67sE7PmOHhE= go.opentelemetry.io/contrib/propagators/ot v1.19.0/go.mod h1:S2Uc7th2ZmLiHu0lrCmDCgTQ/y5Nbbis+TNjR1jjm4Q= go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 h1:k0k7hFNDd8K4iOMJXj7s8sHaC4mhTlAeppRmZXLgZ6k= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 h1:HgbDTD8pioFdY3NRc/YCvsWjqQPtweGyXxa32LgnTOw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0/go.mod h1:tmvt/yK5Es5d6lHYWerLSOna8lCEfrBVX/a9M0ggqss= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 h1:IAtl+7gua134xcV3NieDhJHjjOVeJhXAnYf/0hswjUY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0/go.mod h1:w+pXobnBzh95MNIkeIuAKcHe/Uu/CX2PKIvBP6ipKRA= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32ay7mJG2leczfREEhoW3VfSZIvHaB+gvVo1o8DQ8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4= go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 h1:XzjGkawtAXs20Y+s6k1GNDMBsMDOV28TOT8cxmE42qM= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0/go.mod h1:HAomEgjcKZk3VJ+HHdHLnhZXeGqdzPxxNTdKYRopUXY= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes= go.opentelemetry.io/otel/exporters/zipkin v1.18.0 h1:ZqrHgvega5NIiScTiVrtpZSpEmjUdwzkhuuCEIMAp+s= @@ -1224,8 +1240,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I= +google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/internal/services/catalog_read_service/internal/products/configurations/products_module_configurator.go b/internal/services/catalog_read_service/internal/products/configurations/products_module_configurator.go index ef39b6f3..d32d6c13 100644 --- a/internal/services/catalog_read_service/internal/products/configurations/products_module_configurator.go +++ b/internal/services/catalog_read_service/internal/products/configurations/products_module_configurator.go @@ -25,13 +25,13 @@ func NewProductsModuleConfigurator( func (c *ProductsModuleConfigurator) ConfigureProductsModule() { c.ResolveFunc( func(logger logger2.Logger, mongoRepository data.ProductRepository, cacheRepository data.ProductCacheRepository, tracer tracing.AppTracer) error { - // Config Products Mediators + // config Products Mediators err := mediator.ConfigProductsMediator(logger, mongoRepository, cacheRepository, tracer) if err != nil { return err } - // Config Products Mappings + // config Products Mappings err = mappings.ConfigureProductsMappings() if err != nil { return err @@ -42,7 +42,7 @@ func (c *ProductsModuleConfigurator) ConfigureProductsModule() { } func (c *ProductsModuleConfigurator) MapProductsEndpoints() { - // Config Products Http Endpoints + // config Products Http Endpoints c.ResolveFuncWithParamTag(func(endpoints []route.Endpoint) { for _, endpoint := range endpoints { endpoint.MapEndpoint() diff --git a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/catalogs_configurator.go b/internal/services/catalog_read_service/internal/shared/configurations/catalogs/catalogs_configurator.go index 6cad889b..ccd5b53e 100644 --- a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/catalogs_configurator.go +++ b/internal/services/catalog_read_service/internal/shared/configurations/catalogs/catalogs_configurator.go @@ -49,7 +49,7 @@ func (ic *CatalogsServiceConfigurator) MapCatalogsEndpoints() { func(catalogsServer customEcho.EchoHttpServer, cfg *config.Config) error { catalogsServer.SetupDefaultMiddlewares() - // Config catalogs root endpoint + // config catalogs root endpoint catalogsServer.RouteBuilder(). RegisterRoutes(func(e *echo.Echo) { e.GET("", func(ec echo.Context) error { @@ -63,7 +63,7 @@ func (ic *CatalogsServiceConfigurator) MapCatalogsEndpoints() { }) }) - // Config catalogs swagger + // config catalogs swagger ic.configSwagger(catalogsServer.RouteBuilder()) return nil diff --git a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go b/internal/services/catalog_read_service/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go index 8a2fcfbc..1389e6e4 100644 --- a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go +++ b/internal/services/catalog_read_service/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go @@ -1,7 +1,7 @@ package catalogs import ( - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/docs" "github.com/labstack/echo/v4" diff --git a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go b/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go index 52f6a59f..9e39923e 100644 --- a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go +++ b/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go @@ -7,7 +7,7 @@ import ( customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" @@ -26,7 +26,6 @@ var Module = fx.Module( customEcho.Module, grpc.Module, mongodb.Module, - otel.Module, redis.Module, rabbitmq.ModuleFunc( func(v *validator.Validate, l logger.Logger, tracer tracing.AppTracer) configurations.RabbitMQConfigurationBuilderFuc { @@ -36,6 +35,8 @@ var Module = fx.Module( }, ), health.Module, + tracing.Module, + metrics.Module, // Other provides fx.Provide(validator.New), diff --git a/internal/services/catalog_write_service/config/config.development.json b/internal/services/catalog_write_service/config/config.development.json index 83a9dcef..01b23675 100644 --- a/internal/services/catalog_write_service/config/config.development.json +++ b/internal/services/catalog_write_service/config/config.development.json @@ -48,24 +48,43 @@ "httpPort": 15672 } }, - "openTelemetryOptions": { + "tracingOptions": { "enable": true, "serviceName": "catalogs-write-service", - "instrumentationName": "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice", + "instrumentationName": "io.opentelemetry.traces.catalogs-write-service", "id": 1, "useStdout": false, "alwaysOnSampler": true, "jaegerExporterOptions": { - "otlpEndpoint": "localhost:4317" + "otlpEndpoint": "localhost:4320", + "enabled": true }, "zipkinExporterOptions": { "url": "http://localhost:9411/api/v2/spans" }, - "otelMetricsOptions": { - "port": ":3001", - "metricsRoutePath": "/metrics", - "name": "catalogs-write-service" - } + "otlpProviders": [ + { + "name": "uptrace", + "enabled": false, + "otlpEndpoint": "otlp.uptrace.dev:4317", + "otlpHeaders": { + "uptrace-dsn": "https://@uptrace.dev/" + } + }, + { + "name": "elastic-apm", + "enabled": false, + "otlpEndpoint": "host.docker.internal:4317", + "otlpHeaders": { + "Authorization": "Bearer ${ELASTIC_APM_SECRET_TOKEN}" + } + } + ] + }, + "metricsOptions": { + "metricsRoutePath": "metrics", + "serviceName": "catalogs-write-service", + "instrumentationName": "io.opentelemetry.metrics.catalogs-write-service" }, "eventStoreDbOptions": { "connectionString": "esdb://localhost:2113?tls=false" diff --git a/internal/services/catalog_write_service/config/config.test.json b/internal/services/catalog_write_service/config/config.test.json index 73fdeed1..45fdc4de 100644 --- a/internal/services/catalog_write_service/config/config.test.json +++ b/internal/services/catalog_write_service/config/config.test.json @@ -48,24 +48,33 @@ "httpPort": 15672 } }, - "openTelemetryOptions": { + "tracingOptions": { "enable": true, "serviceName": "catalogs-write-service", - "instrumentationName": "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice", + "instrumentationName": "io.opentelemetry.traces.catalogs-write-service", "id": 1, - "useStdout": true, + "useStdout": false, "alwaysOnSampler": true, "jaegerExporterOptions": { - "otlpEndpoint": "localhost:4317" + "otlpEndpoint": "localhost:4320", + "enabled": true }, "zipkinExporterOptions": { "url": "http://localhost:9411/api/v2/spans" }, - "otelMetricsOptions": { - "port": ":3001", - "metricsRoutePath": "/metrics", - "name": "catalogs-write-service" - } + "otlpProviders": [ + { + "name": "uptrace", + "enabled": false, + "otlpEndpoint": "otlp.uptrace.dev:4317", + "otlpHeaders": {} + } + ] + }, + "metricsOptions": { + "metricsRoutePath": "metrics", + "serviceName": "catalogs-write-service", + "instrumentationName": "io.opentelemetry.metrics.catalogs-write-service" }, "eventStoreDbOptions": { "connectionString": "esdb://localhost:2113?tls=false" diff --git a/internal/services/catalog_write_service/go.mod b/internal/services/catalog_write_service/go.mod index 85fd3478..d687ac8c 100644 --- a/internal/services/catalog_write_service/go.mod +++ b/internal/services/catalog_write_service/go.mod @@ -30,7 +30,7 @@ require ( go.opentelemetry.io/otel/metric v1.18.0 go.opentelemetry.io/otel/trace v1.18.0 go.uber.org/fx v1.20.0 - google.golang.org/grpc v1.58.1 + google.golang.org/grpc v1.58.2 gopkg.in/khaiql/dbcleaner.v2 v2.3.0 gorm.io/gorm v1.25.4 ) @@ -47,7 +47,7 @@ require ( github.com/KyleBanks/depth v1.2.1 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/Microsoft/hcsshim v0.11.0 // indirect + github.com/Microsoft/hcsshim v0.11.1 // indirect github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 // indirect github.com/ahmetb/go-linq/v3 v3.2.0 // indirect github.com/ajg/form v1.5.1 // indirect @@ -166,6 +166,7 @@ require ( github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect github.com/uptrace/bun v1.1.16 // indirect github.com/uptrace/bun/driver/pgdriver v1.1.16 // indirect + github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2 // indirect github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 // indirect github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect @@ -189,10 +190,14 @@ require ( go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 // indirect go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 // indirect + go.opentelemetry.io/contrib/instrumentation/host v0.44.0 // indirect go.opentelemetry.io/contrib/propagators/ot v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 // indirect go.opentelemetry.io/otel/exporters/prometheus v0.41.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 // indirect go.opentelemetry.io/otel/exporters/zipkin v1.18.0 // indirect go.opentelemetry.io/otel/sdk v1.18.0 // indirect @@ -231,8 +236,8 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/procfs v0.11.1 // indirect - github.com/spf13/afero v1.9.5 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/spf13/afero v1.10.0 // indirect github.com/spf13/cast v1.5.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect diff --git a/internal/services/catalog_write_service/go.sum b/internal/services/catalog_write_service/go.sum index 260213e1..5e572a44 100644 --- a/internal/services/catalog_write_service/go.sum +++ b/internal/services/catalog_write_service/go.sum @@ -87,8 +87,8 @@ github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA4 github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.11.0 h1:7EFNIY4igHEXUdj1zXgAyU3fLc7QfOKHbkldRVTBdiM= -github.com/Microsoft/hcsshim v0.11.0/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= +github.com/Microsoft/hcsshim v0.11.1 h1:hJ3s7GbWlGK4YVV92sO88BQSyF4ZLVy7/awqOlPxFbA= +github.com/Microsoft/hcsshim v0.11.1/go.mod h1:nFJmaO4Zr5Y7eADdFOpYswDDlNVbvcIJJNJLECr5JQg= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4= @@ -347,8 +347,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 h1:gpptm606MZYGaMHMsB4Srmb6EbW/IVHnt04rcMXnkBQ= +github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -571,8 +571,8 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= -github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/ginkgo/v2 v2.12.1 h1:uHNEO1RP2SpuZApSkel9nEh1/Mu+hmQe7Q+Pepg5OYA= +github.com/onsi/ginkgo/v2 v2.12.1/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -622,8 +622,8 @@ github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUo github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= @@ -684,8 +684,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= +github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= @@ -744,6 +744,8 @@ github.com/uptrace/bun v1.1.16 h1:cn9cgEMFwcyYRsQLfxCRMUxyK1WaHwOVrR3TvzEFZ/A= github.com/uptrace/bun v1.1.16/go.mod h1:7HnsMRRvpLFUcquJxp22JO8PsWKpFQO/gNXqqsuGWg8= github.com/uptrace/bun/driver/pgdriver v1.1.16 h1:b/NiSXk6Ldw7KLfMLbOqIkm4odHd7QiNOCPLqPFJjK4= github.com/uptrace/bun/driver/pgdriver v1.1.16/go.mod h1:Rmfbc+7lx1z/umjMyAxkOHK81LgnGj71XC5YpA6k1vU= +github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2 h1:s3quVevwQlgEMCkvscS/VHo92amtyMzRfcuOZqfevrM= +github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2/go.mod h1:IJLBT7ItgUACTEoq6BEw/9HwHWL4BiPirYgKhZS83Lg= github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 h1:CNznWHkrbA6o1q2H/BsH4tIHf4zbKNtndeoV+AH8z0U= github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2/go.mod h1:7YSrHCmYPHIXjTWnKSU7EGT0TFEcm3WwSeQquwCGg38= github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 h1:uyrW06oJi4iWvhjPLVfk4qrSP2Zm0AMozKKDmp6i4pE= @@ -821,18 +823,26 @@ go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/ot go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0/go.mod h1:JH6FxBlkXo/cYoU/m65W5dOQ6sqPL+jHtSJaSE7/+XQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 h1:b8xjZxHbLrXAum4SxJd1Rlm7Y/fKaB+6ACI7/e5EfSA= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0/go.mod h1:1ei0a32xOGkFoySu7y1DAHfcuIhC0pNZpvY2huXuMy4= +go.opentelemetry.io/contrib/instrumentation/host v0.44.0 h1:SNqDjPpQmwFYvDipyJJxDbU5zKNWiYSMii864ubzIuQ= +go.opentelemetry.io/contrib/instrumentation/host v0.44.0/go.mod h1:bZcqg3yy0riQLNkx8dJWV4J3tbfL+6LQ5lIbI+vmarE= go.opentelemetry.io/contrib/propagators/b3 v1.19.0 h1:ulz44cpm6V5oAeg5Aw9HyqGFMS6XM7untlMEhD7YzzA= go.opentelemetry.io/contrib/propagators/b3 v1.19.0/go.mod h1:OzCmE2IVS+asTI+odXQstRGVfXQ4bXv9nMBRK0nNyqQ= go.opentelemetry.io/contrib/propagators/ot v1.19.0 h1:vODRLMlKN4ApM8ri0UDk8nnEeISuwxpf67sE7PmOHhE= go.opentelemetry.io/contrib/propagators/ot v1.19.0/go.mod h1:S2Uc7th2ZmLiHu0lrCmDCgTQ/y5Nbbis+TNjR1jjm4Q= go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 h1:k0k7hFNDd8K4iOMJXj7s8sHaC4mhTlAeppRmZXLgZ6k= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 h1:HgbDTD8pioFdY3NRc/YCvsWjqQPtweGyXxa32LgnTOw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0/go.mod h1:tmvt/yK5Es5d6lHYWerLSOna8lCEfrBVX/a9M0ggqss= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 h1:IAtl+7gua134xcV3NieDhJHjjOVeJhXAnYf/0hswjUY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0/go.mod h1:w+pXobnBzh95MNIkeIuAKcHe/Uu/CX2PKIvBP6ipKRA= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32ay7mJG2leczfREEhoW3VfSZIvHaB+gvVo1o8DQ8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4= go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 h1:XzjGkawtAXs20Y+s6k1GNDMBsMDOV28TOT8cxmE42qM= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0/go.mod h1:HAomEgjcKZk3VJ+HHdHLnhZXeGqdzPxxNTdKYRopUXY= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes= go.opentelemetry.io/otel/exporters/zipkin v1.18.0 h1:ZqrHgvega5NIiScTiVrtpZSpEmjUdwzkhuuCEIMAp+s= @@ -1264,8 +1274,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I= +google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/internal/services/catalog_write_service/internal/products/configurations/products_module_configurator.go b/internal/services/catalog_write_service/internal/products/configurations/products_module_configurator.go index a13481f1..e5ee7b47 100644 --- a/internal/services/catalog_write_service/internal/products/configurations/products_module_configurator.go +++ b/internal/services/catalog_write_service/internal/products/configurations/products_module_configurator.go @@ -31,7 +31,7 @@ func NewProductsModuleConfigurator( func (c *ProductsModuleConfigurator) ConfigureProductsModule() { c.ResolveFunc( func(logger logger.Logger, uow data.CatalogUnitOfWork, productRepository data.ProductRepository, producer producer.Producer, tracer tracing.AppTracer) error { - // Config Products Mediators + // config Products Mediators err := mediatr.ConfigProductsMediator(logger, uow, productRepository, producer, tracer) if err != nil { return err @@ -49,14 +49,14 @@ func (c *ProductsModuleConfigurator) ConfigureProductsModule() { } func (c *ProductsModuleConfigurator) MapProductsEndpoints() { - // Config Products Http Endpoints + // config Products Http Endpoints c.ResolveFunc(func(endpointParams params.ProductsEndpointsParams) { for _, endpoint := range endpointParams.Endpoints { endpoint.MapEndpoint() } }) - // Config Products Grpc Endpoints + // config Products Grpc Endpoints c.ResolveFunc( func(catalogsGrpcServer grpcServer.GrpcServer, grpcService *grpc.ProductGrpcServiceServer) error { catalogsGrpcServer.GrpcServiceBuilder().RegisterRoutes(func(server *googleGrpc.Server) { diff --git a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/endpoints/create_product_endpoint.go b/internal/services/catalog_write_service/internal/products/features/creating_product/v1/endpoints/create_product_endpoint.go index a745d35b..66a444b4 100644 --- a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/endpoints/create_product_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/creating_product/v1/endpoints/create_product_endpoint.go @@ -50,7 +50,10 @@ func (ep *createProductEndpoint) handler() echo.HandlerFunc { "[createProductEndpoint_handler.Bind] error in the binding request", ) ep.Logger.Errorf( - fmt.Sprintf("[createProductEndpoint_handler.Bind] err: %v", badRequestErr), + fmt.Sprintf( + "[createProductEndpoint_handler.Bind] err: %v", + badRequestErr, + ), ) } @@ -65,8 +68,12 @@ func (ep *createProductEndpoint) handler() echo.HandlerFunc { "[createProductEndpoint_handler.StructCtx] command validation failed", ) ep.Logger.Errorf( - fmt.Sprintf("[createProductEndpoint_handler.StructCtx] err: {%v}", validationErr), + fmt.Sprintf( + "[createProductEndpoint_handler.StructCtx] err: {%v}", + validationErr, + ), ) + return validationErr } diff --git a/internal/services/catalog_write_service/internal/products/products_fx.go b/internal/services/catalog_write_service/internal/products/products_fx.go index dfe0d070..cdb6b053 100644 --- a/internal/services/catalog_write_service/internal/products/products_fx.go +++ b/internal/services/catalog_write_service/internal/products/products_fx.go @@ -1,7 +1,7 @@ package products import ( - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/repositories" createProductV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/endpoints" @@ -23,22 +23,40 @@ var Module = fx.Module( fx.Provide(repositories.NewPostgresProductRepository), fx.Provide(grpc.NewProductGrpcService), - fx.Provide(fx.Annotate(func(catalogsServer customEcho.EchoHttpServer) *echo.Group { - var g *echo.Group - catalogsServer.RouteBuilder().RegisterGroupFunc("/api/v1", func(v1 *echo.Group) { - group := v1.Group("/products") - g = group - }) + fx.Provide( + fx.Annotate(func(catalogsServer contracts.EchoHttpServer) *echo.Group { + var g *echo.Group + catalogsServer.RouteBuilder(). + RegisterGroupFunc("/api/v1", func(v1 *echo.Group) { + group := v1.Group("/products") + g = group + }) - return g - }, fx.ResultTags(`name:"product-echo-group"`))), + return g + }, fx.ResultTags(`name:"product-echo-group"`)), + ), fx.Provide( - route.AsRoute(createProductV1.NewCreteProductEndpoint, "product-routes"), - route.AsRoute(updateProductsV1.NewUpdateProductEndpoint, "product-routes"), + route.AsRoute( + createProductV1.NewCreteProductEndpoint, + "product-routes", + ), + route.AsRoute( + updateProductsV1.NewUpdateProductEndpoint, + "product-routes", + ), route.AsRoute(getProductsV1.NewGetProductsEndpoint, "product-routes"), - route.AsRoute(searchProductsV1.NewSearchProductsEndpoint, "product-routes"), - route.AsRoute(getProductByIdV1.NewGetProductByIdEndpoint, "product-routes"), - route.AsRoute(deleteProductV1.NewDeleteProductEndpoint, "product-routes"), + route.AsRoute( + searchProductsV1.NewSearchProductsEndpoint, + "product-routes", + ), + route.AsRoute( + getProductByIdV1.NewGetProductByIdEndpoint, + "product-routes", + ), + route.AsRoute( + deleteProductV1.NewDeleteProductEndpoint, + "product-routes", + ), ), ) diff --git a/internal/services/catalog_write_service/internal/shared/app/test/test_app.go b/internal/services/catalog_write_service/internal/shared/app/test/test_app.go index b3ff7249..03cd6566 100644 --- a/internal/services/catalog_write_service/internal/shared/app/test/test_app.go +++ b/internal/services/catalog_write_service/internal/shared/app/test/test_app.go @@ -12,7 +12,6 @@ import ( config3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" contracts2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/contracts" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/goose" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/bus" config2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/testcontainer/gorm" @@ -54,9 +53,10 @@ func (a *TestApp) Run(t *testing.T) (result *TestAppResult) { // ref: https://github.com/uber-go/fx/blob/master/app_test.go appBuilder := NewCatalogsWriteTestApplicationBuilder(t) appBuilder.ProvideModule(catalogs.CatalogsServiceModule) - appBuilder.ProvideModule(goose.Module) - appBuilder.Decorate(rabbitmq.RabbitmqContainerOptionsDecorator(t, lifetimeCtx)) + appBuilder.Decorate( + rabbitmq.RabbitmqContainerOptionsDecorator(t, lifetimeCtx), + ) appBuilder.Decorate(gorm.GormContainerOptionsDecorator(t, lifetimeCtx)) testApp := appBuilder.Build() diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator.go b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator.go index 063896eb..94d03293 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator.go +++ b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator.go @@ -5,7 +5,8 @@ import ( "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + echocontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" + contracts2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/infrastructure" @@ -20,9 +21,13 @@ type CatalogsServiceConfigurator struct { productsModuleConfigurator *configurations.ProductsModuleConfigurator } -func NewCatalogsServiceConfigurator(app contracts.Application) *CatalogsServiceConfigurator { +func NewCatalogsServiceConfigurator( + app contracts.Application, +) *CatalogsServiceConfigurator { infraConfigurator := infrastructure.NewInfrastructureConfigurator(app) - productModuleConfigurator := configurations.NewProductsModuleConfigurator(app) + productModuleConfigurator := configurations.NewProductsModuleConfigurator( + app, + ) return &CatalogsServiceConfigurator{ Application: app, @@ -38,14 +43,16 @@ func (ic *CatalogsServiceConfigurator) ConfigureCatalogs() { // Shared // Catalogs configurations - ic.ResolveFunc(func(gorm *gorm.DB) error { - err := ic.migrateCatalogs(gorm) - if err != nil { - return err - } + ic.ResolveFunc( + func(gorm *gorm.DB, postgresMigrationRunner contracts2.PostgresMigrationRunner) error { + err := ic.migrateCatalogs(gorm, postgresMigrationRunner) + if err != nil { + return err + } - return nil - }) + return nil + }, + ) // Modules // Product module @@ -55,21 +62,24 @@ func (ic *CatalogsServiceConfigurator) ConfigureCatalogs() { func (ic *CatalogsServiceConfigurator) MapCatalogsEndpoints() { // Shared ic.ResolveFunc( - func(catalogsServer customEcho.EchoHttpServer, options *config.AppOptions) error { + func(catalogsServer echocontracts.EchoHttpServer, options *config.AppOptions) error { catalogsServer.SetupDefaultMiddlewares() - // Config catalogs root endpoint + // config catalogs root endpoint catalogsServer.RouteBuilder(). RegisterRoutes(func(e *echo.Echo) { e.GET("", func(ec echo.Context) error { return ec.String( http.StatusOK, - fmt.Sprintf("%s is running...", options.GetMicroserviceNameUpper()), + fmt.Sprintf( + "%s is running...", + options.GetMicroserviceNameUpper(), + ), ) }) }) - // Config catalogs swagger + // config catalogs swagger ic.configSwagger(catalogsServer.RouteBuilder()) return nil diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator_migration.go b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator_migration.go index c79f8ba9..fea9b6c4 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator_migration.go +++ b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator_migration.go @@ -1,18 +1,33 @@ package catalogs import ( + "context" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/contracts" + "gorm.io/gorm" ) -func (ic *CatalogsServiceConfigurator) migrateCatalogs(gorm *gorm.DB) error { +func (ic *CatalogsServiceConfigurator) migrateCatalogs( + gorm *gorm.DB, + runner contracts.PostgresMigrationRunner, +) error { // - for complex migration and ability to back-track to specific migration revision it is better we use `goose`, but if we want to use built-in gorm migration we can also sync gorm with `atlas` integration migration versioning for getting migration history from grom changes // - here I used goose for migration, with using cmd/migration file // https://atlasgo.io/guides/orms/gorm - //err := gorm.AutoMigrate(&models.Product{}) //if err != nil { // return err //} - return nil + // migration with Goorse + return ic.migrateGoose(runner) +} + +func (ic *CatalogsServiceConfigurator) migrateGoose( + runner contracts.PostgresMigrationRunner, +) error { + err := runner.Up(context.Background(), 0) + + return err } diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go index 72938eaf..e45480b9 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go +++ b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go @@ -1,7 +1,7 @@ package catalogs import ( - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/docs" "github.com/labstack/echo/v4" diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go index 9e020634..46c1a139 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go +++ b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go @@ -6,7 +6,9 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health" customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/goose" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" rabbitmq2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations/rabbitmq" @@ -24,7 +26,7 @@ var Module = fx.Module( customEcho.Module, grpc.Module, gormPostgres.Module, - otel.Module, + goose.Module, rabbitmq.ModuleFunc( func() configurations.RabbitMQConfigurationBuilderFuc { return func(builder configurations.RabbitMQConfigurationBuilder) { @@ -33,6 +35,8 @@ var Module = fx.Module( }, ), health.Module, + tracing.Module, + metrics.Module, // Other provides fx.Provide(validator.New), diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_test_fx.go b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_test_fx.go deleted file mode 100644 index 428b7c6d..00000000 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_test_fx.go +++ /dev/null @@ -1,10 +0,0 @@ -package infrastructure - -//var TestModule = func(t *testing.T, ctx context.Context) fx.Option { -// return fx.Module( -// "infrastructuretestfx", -// // Modules -// gorm.ModuleFunc(t, ctx), -// rabbitmq.ModuleFunc(t, ctx), -// ) -//} diff --git a/internal/services/catalog_write_service/internal/shared/test_fixtures/integration/integration_test_fixture.go b/internal/services/catalog_write_service/internal/shared/test_fixtures/integration/integration_test_fixture.go index 5eb2ced3..d777f788 100644 --- a/internal/services/catalog_write_service/internal/shared/test_fixtures/integration/integration_test_fixture.go +++ b/internal/services/catalog_write_service/internal/shared/test_fixtures/integration/integration_test_fixture.go @@ -74,8 +74,6 @@ func NewIntegrationTestSharedFixture( ProductServiceClient: result.ProductServiceClient, } - migrateDatabase(result) - return shared } @@ -215,10 +213,3 @@ func seedAndMigration(gormDB *gorm.DB) ([]*models.Product, error) { ) return result.Items, nil } - -func migrateDatabase(result *test.TestAppResult) { - err := result.PostgresMigrationRunner.Up(context.Background(), 0) - if err != nil { - result.Logger.Fatalf("error in catalog_service migration, err: %s", err) - } -} diff --git a/internal/services/order_service/config/config.development.json b/internal/services/order_service/config/config.development.json index 5dca0a45..059bf573 100644 --- a/internal/services/order_service/config/config.development.json +++ b/internal/services/order_service/config/config.development.json @@ -48,24 +48,43 @@ "httpPort": 15672 } }, - "openTelemetryOptions": { + "tracingOptions": { "enable": true, "serviceName": "orders-service", - "instrumentationName": "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice", - "id": 3, - "alwaysOnSampler": true, + "instrumentationName": "io.opentelemetry.traces.orders-service", + "id": 1, "useStdout": false, + "alwaysOnSampler": true, "jaegerExporterOptions": { - "otlpEndpoint": "localhost:4317" + "otlpEndpoint": "localhost:4320", + "enabled": true }, "zipkinExporterOptions": { "url": "http://localhost:9411/api/v2/spans" }, - "otelMetricsOptions": { - "port": ":2003", - "metricsRoutePath": "/metrics", - "name": "orders-service" - } + "otlpProviders": [ + { + "name": "uptrace", + "enabled": false, + "otlpEndpoint": "otlp.uptrace.dev:4317", + "otlpHeaders": { + "uptrace-dsn": "https://@uptrace.dev/" + } + }, + { + "name": "elastic-apm", + "enabled": false, + "otlpEndpoint": "host.docker.internal:4317", + "otlpHeaders": { + "Authorization": "Bearer ${ELASTIC_APM_SECRET_TOKEN}" + } + } + ] + }, + "metricsOptions": { + "metricsRoutePath": "/metrics", + "serviceName": "orders-service", + "instrumentationName": "io.opentelemetry.metrics.orders-service" }, "eventStoreDbOptions": { "host": "localhost", diff --git a/internal/services/order_service/config/config.test.json b/internal/services/order_service/config/config.test.json index a4425c15..c9f14c9c 100644 --- a/internal/services/order_service/config/config.test.json +++ b/internal/services/order_service/config/config.test.json @@ -46,24 +46,43 @@ "httpPort": 15672 } }, - "openTelemetryOptions": { + "tracingOptions": { "enable": true, "serviceName": "orders-service", - "instrumentationName": "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice", - "id": 3, - "alwaysOnSampler": true, + "instrumentationName": "io.opentelemetry.traces.orders-service", + "id": 1, "useStdout": false, + "alwaysOnSampler": true, "jaegerExporterOptions": { - "otlpEndpoint": "localhost:4317" + "otlpEndpoint": "localhost:4320", + "enabled": true }, "zipkinExporterOptions": { "url": "http://localhost:9411/api/v2/spans" }, - "otelMetricsOptions": { - "port": ":3003", - "metricsRoutePath": "/metrics", - "name": "orders-service" - } + "otlpProviders": [ + { + "name": "uptrace", + "enabled": false, + "otlpEndpoint": "otlp.uptrace.dev:4317", + "otlpHeaders": { + "uptrace-dsn": "https://@uptrace.dev/" + } + }, + { + "name": "elastic-apm", + "enabled": false, + "otlpEndpoint": "host.docker.internal:4317", + "otlpHeaders": { + "Authorization": "Bearer ${ELASTIC_APM_SECRET_TOKEN}" + } + } + ] + }, + "metricsOptions": { + "metricsRoutePath": "/metrics", + "serviceName": "orders-service", + "instrumentationName": "io.opentelemetry.metrics.orders-service" }, "eventStoreDbOptions": { "host": "localhost", diff --git a/internal/services/order_service/go.mod b/internal/services/order_service/go.mod index 051daa60..9c38edc9 100644 --- a/internal/services/order_service/go.mod +++ b/internal/services/order_service/go.mod @@ -201,6 +201,7 @@ require ( go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 // indirect go.opentelemetry.io/otel/exporters/prometheus v0.41.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 // indirect go.opentelemetry.io/otel/exporters/zipkin v1.18.0 // indirect go.opentelemetry.io/otel/sdk v1.18.0 // indirect diff --git a/internal/services/order_service/go.sum b/internal/services/order_service/go.sum index 63142433..fe6ca576 100644 --- a/internal/services/order_service/go.sum +++ b/internal/services/order_service/go.sum @@ -801,6 +801,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32a go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4= go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 h1:XzjGkawtAXs20Y+s6k1GNDMBsMDOV28TOT8cxmE42qM= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0/go.mod h1:HAomEgjcKZk3VJ+HHdHLnhZXeGqdzPxxNTdKYRopUXY= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes= go.opentelemetry.io/otel/exporters/zipkin v1.18.0 h1:ZqrHgvega5NIiScTiVrtpZSpEmjUdwzkhuuCEIMAp+s= diff --git a/internal/services/order_service/internal/orders/configurations/orders_module_configurator.go b/internal/services/order_service/internal/orders/configurations/orders_module_configurator.go index 91452983..fb831bf2 100644 --- a/internal/services/order_service/internal/orders/configurations/orders_module_configurator.go +++ b/internal/services/order_service/internal/orders/configurations/orders_module_configurator.go @@ -40,13 +40,13 @@ func (c *OrdersModuleConfigurator) ConfigureOrdersModule() { orderAggregateStore store.AggregateStore[*aggregate.Order], tracer tracing.AppTracer, ) error { - // Config Orders Mappings + // config Orders Mappings err := mappings.ConfigureOrdersMappings() if err != nil { return err } - // Config Orders Mediators + // config Orders Mediators err = mediatr.ConfigOrdersMediator(logger, orderRepository, orderAggregateStore, tracer) if err != nil { return err @@ -58,7 +58,7 @@ func (c *OrdersModuleConfigurator) ConfigureOrdersModule() { } func (c *OrdersModuleConfigurator) MapOrdersEndpoints() { - // Config Orders Http Endpoints + // config Orders Http Endpoints c.ResolveFuncWithParamTag(func(endpoints []route.Endpoint) { for _, endpoint := range endpoints { endpoint.MapEndpoint() @@ -66,7 +66,7 @@ func (c *OrdersModuleConfigurator) MapOrdersEndpoints() { }, `group:"order-routes"`, ) - // Config Orders Grpc Endpoints + // config Orders Grpc Endpoints c.ResolveFunc( func(ordersGrpcServer grpcServer.GrpcServer, ordersMetrics *contracts.OrdersMetrics, logger logger.Logger, validator *validator.Validate) error { orderGrpcService := grpc.NewOrderGrpcService(logger, validator, ordersMetrics) diff --git a/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_fx.go b/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_fx.go index db042abb..f736ac5d 100644 --- a/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_fx.go +++ b/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_fx.go @@ -8,7 +8,8 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health" customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" rabbitmq2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/configurations/rabbitmq" @@ -35,7 +36,6 @@ var Module = fx.Module( } }, ), - otel.Module, rabbitmq.ModuleFunc( func() configurations.RabbitMQConfigurationBuilderFuc { return func(builder configurations.RabbitMQConfigurationBuilder) { @@ -44,6 +44,8 @@ var Module = fx.Module( }, ), health.Module, + tracing.Module, + metrics.Module, // Other provides fx.Provide(validator.New), diff --git a/internal/services/order_service/internal/shared/configurations/orders/orders_configurator.go b/internal/services/order_service/internal/shared/configurations/orders/orders_configurator.go index 3e47f567..24d98ef5 100644 --- a/internal/services/order_service/internal/shared/configurations/orders/orders_configurator.go +++ b/internal/services/order_service/internal/shared/configurations/orders/orders_configurator.go @@ -51,7 +51,7 @@ func (ic *OrdersServiceConfigurator) MapOrdersEndpoints() { func(ordersServer customEcho.EchoHttpServer, cfg *config.Config) error { ordersServer.SetupDefaultMiddlewares() - // Config orders root endpoint + // config orders root endpoint ordersServer.RouteBuilder(). RegisterRoutes(func(e *echo.Echo) { e.GET("", func(ec echo.Context) error { @@ -65,7 +65,7 @@ func (ic *OrdersServiceConfigurator) MapOrdersEndpoints() { }) }) - // Config orders swagger + // config orders swagger ic.configSwagger(ordersServer.RouteBuilder()) return nil diff --git a/internal/services/order_service/internal/shared/configurations/orders/orders_configurator_swagger.go b/internal/services/order_service/internal/shared/configurations/orders/orders_configurator_swagger.go index ed1313ce..74c4be25 100644 --- a/internal/services/order_service/internal/shared/configurations/orders/orders_configurator_swagger.go +++ b/internal/services/order_service/internal/shared/configurations/orders/orders_configurator_swagger.go @@ -1,7 +1,7 @@ package orders import ( - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/docs" "github.com/labstack/echo/v4" diff --git a/scripts/service-reset.ps1 b/scripts/service-reset.ps1 new file mode 100644 index 00000000..954d36d0 --- /dev/null +++ b/scripts/service-reset.ps1 @@ -0,0 +1,2 @@ +net stop winnat +net start winnat From 26bf420e7bf03d7e6f7748bc444ff991fee8f03c Mon Sep 17 00:00:00 2001 From: mehdihadeli Date: Wed, 4 Oct 2023 14:58:47 +0330 Subject: [PATCH 03/15] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20refactor?= =?UTF-8?q?=20tracing=20and=20metrics?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...cker-compose.infrastructure-collector.yaml | 160 ++++-- .../docker-compose.infrastructure.yaml | 168 ++++-- .../monitoring/grafana-bootstrap.ini | 2 + .../docker-compose/monitoring/grafana.yaml | 36 +- .../docker-compose/monitoring/prometheus.yml | 17 +- .../otelcollector/otelcol-config.yml | 3 +- .../docker-compose/otelcollector/tempo.yaml | 57 ++ internal/pkg/go.mod | 61 +-- internal/pkg/go.sum | 125 +++-- internal/pkg/grpc/client.go | 15 +- .../pkg/grpc/grpcErrors/grpc_error_parser.go | 34 +- internal/pkg/grpc/grpc_fx.go | 13 +- internal/pkg/grpc/handlers/config.go | 80 +++ internal/pkg/grpc/handlers/handler.go | 327 +++++++++++ internal/pkg/grpc/handlers/supplier.go | 53 ++ .../grpc_error/error_interceptor.go | 41 +- .../request_status_interceptor.go | 84 --- internal/pkg/grpc/server.go | 27 +- internal/pkg/http/custom_echo/echo_server.go | 70 +-- .../hadnlers/problem_details_handler.go | 28 - .../hadnlers/problemdetail_error_handler.go | 29 + .../middlewares/log/log_middleware.go | 4 +- .../middlewares/otel_metrics/config.go | 97 +++- .../middlewares/otel_metrics/metric.go | 369 +++++++++++++ .../otel_metrics/metrics_middleware.go | 79 +++ .../otel_metrics/request_status_middleware.go | 55 -- .../middlewares/otel_metrics/v0/prometheus.go | 518 ------------------ .../middlewares/otel_metrics/v1/metric.go | 193 ------- .../middlewares/otel_metrics/v1/middleware.go | 49 -- .../middlewares/otel_metrics/v1/view.go | 26 - .../middlewares/otel_metrics/v2/otel-meter.go | 446 --------------- .../middlewares/otel_metrics/view.go | 33 ++ .../middlewares/otel_tracing/config.go | 72 +++ .../otel_tracing/tracing_middleware.go | 96 ++++ .../middlewares/problem_detail/config.go | 34 ++ .../problem_detail_middleware.go | 44 ++ .../pkg/http/custom_echo/utils/tracing.go | 80 ++- .../http_errors/custom_errors/api_error.go | 8 +- .../custom_errors/application_error.go | 26 +- .../custom_errors/bad_request_error.go | 7 +- .../custom_errors/conflict_error.go | 7 +- .../http_errors/custom_errors/domain_error.go | 7 +- .../custom_errors/forbiden_error.go | 7 +- .../custom_errors/internal_server_error.go | 7 +- .../custom_errors/marshaling_error.go | 7 +- .../custom_errors/not_found_error.go | 7 +- .../custom_errors/unauthorized_error.go | 7 +- .../custom_errors/unmarshaling_error.go | 7 +- .../custom_errors/validation_error.go | 7 +- .../problemDetails/problem_detail_parser.go | 43 +- internal/pkg/otel/metrics/metrics.go | 54 +- internal/pkg/otel/metrics/metrics_options.go | 1 + internal/pkg/otel/tracing/tracing.go | 56 +- internal/pkg/otel/tracing/tracing_options.go | 2 + .../catalog_read_service/config/config.go | 2 +- internal/services/catalog_read_service/go.mod | 53 +- internal/services/catalog_read_service/go.sum | 116 ++-- .../config/app_options.go | 2 +- .../config/config.development.json | 14 + .../services/catalog_write_service/go.mod | 55 +- .../services/catalog_write_service/go.sum | 120 ++-- .../v1/endpoints/get_products_endpoint.go | 12 +- internal/services/order_service/go.mod | 59 +- internal/services/order_service/go.sum | 128 ++--- .../invalid_delivery_address_error.go | 8 +- .../domain_exceptions/invalid_email_error.go | 9 +- .../order_domain_errors_test.go | 21 + .../order_items_required_errors.go | 8 +- .../order_not_found_error.go | 12 +- 69 files changed, 2418 insertions(+), 2086 deletions(-) create mode 100644 deployments/docker-compose/monitoring/grafana-bootstrap.ini create mode 100644 deployments/docker-compose/otelcollector/tempo.yaml create mode 100644 internal/pkg/grpc/handlers/config.go create mode 100644 internal/pkg/grpc/handlers/handler.go create mode 100644 internal/pkg/grpc/handlers/supplier.go delete mode 100644 internal/pkg/grpc/interceptors/otel_metrics/request_status_interceptor.go delete mode 100644 internal/pkg/http/custom_echo/hadnlers/problem_details_handler.go create mode 100644 internal/pkg/http/custom_echo/hadnlers/problemdetail_error_handler.go create mode 100644 internal/pkg/http/custom_echo/middlewares/otel_metrics/metric.go create mode 100644 internal/pkg/http/custom_echo/middlewares/otel_metrics/metrics_middleware.go delete mode 100644 internal/pkg/http/custom_echo/middlewares/otel_metrics/request_status_middleware.go delete mode 100644 internal/pkg/http/custom_echo/middlewares/otel_metrics/v0/prometheus.go delete mode 100644 internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/metric.go delete mode 100644 internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/middleware.go delete mode 100644 internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/view.go delete mode 100644 internal/pkg/http/custom_echo/middlewares/otel_metrics/v2/otel-meter.go create mode 100644 internal/pkg/http/custom_echo/middlewares/otel_metrics/view.go create mode 100644 internal/pkg/http/custom_echo/middlewares/otel_tracing/config.go create mode 100644 internal/pkg/http/custom_echo/middlewares/otel_tracing/tracing_middleware.go create mode 100644 internal/pkg/http/custom_echo/middlewares/problem_detail/config.go create mode 100644 internal/pkg/http/custom_echo/middlewares/problem_detail/problem_detail_middleware.go diff --git a/deployments/docker-compose/docker-compose.infrastructure-collector.yaml b/deployments/docker-compose/docker-compose.infrastructure-collector.yaml index 436db1ee..e5879a7c 100644 --- a/deployments/docker-compose/docker-compose.infrastructure-collector.yaml +++ b/deployments/docker-compose/docker-compose.infrastructure-collector.yaml @@ -1,5 +1,6 @@ # Ref:https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/examples/demo/docker-compose.yaml # https://github.com/open-telemetry/opentelemetry-demo/blob/main/docker-compose.yml +# https://www.youtube.com/watch?v=EeU-k659lpw version: "3.8" name: go-ecommerce-microservices @@ -78,8 +79,12 @@ services: - "55679:55679" # zpages extension - "1888:1888" # pprof extension depends_on: - - jaeger - - prometheus + prometheus: + condition: service_healthy + tempo: + condition: service_healthy + jaeger: + condition: service_healthy # node_exporter will use for gathering metrics on the system level with its own /metrics endpoint like cpu, ram, ... # https://prometheus.io/docs/guides/node-exporter/ @@ -100,8 +105,46 @@ services: restart: unless-stopped volumes: - ./monitoring/grafana.yaml:/etc/grafana/provisioning/datasources/datasource.yaml + - ./monitoring/grafana-bootstrap.ini:/etc/grafana/grafana.ini ports: - ${GRAFANA_HOST_PORT:-3000}:${GRAFANA_PORT:-3000} + environment: + - GF_AUTH_ANONYMOUS_ENABLED=true + - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin + - GF_AUTH_DISABLE_LOGIN_FORM=true + - GF_FEATURE_TOGGLES_ENABLE=traceqlEditor + healthcheck: + interval: 5s + retries: 10 + test: wget --no-verbose --tries=1 --spider http://localhost:3000 || exit 1 + depends_on: + prometheus: + condition: service_healthy + tempo: + condition: service_healthy + networks: + - ecommerce + + # https://grafana.com/docs/tempo/latest/getting-started/ + # https://github.com/grafana/tempo/blob/main/example/docker-compose/local/docker-compose.yaml + # https://github.com/Domoryonok/tracing_demo/blob/master/grafana/docker-compose.yaml + # https://grafana.com/docs/grafana/latest/datasources/jaeger/ + # https://grafana.com/docs/tempo/latest/operations/architecture/ + tempo: + image: grafana/tempo:latest + command: [ "-search.enabled=true", "-config.file=/etc/tempo.yaml" ] + volumes: + - ./otelcollector/tempo.yaml:/etc/tempo.yaml + - ./tempo-data:/tmp/tempo + ports: + - "3200:3200" # tempo UI + - "4322:4317" # otlp grpc + - "9411" # zipkin - export zipkin traces to tempo + - "14268" # jaeger - export jaeger traces to tempo + healthcheck: + interval: 5s + retries: 10 + test: wget --no-verbose --tries=1 --spider http://localhost:3200/status || exit 1 networks: - ecommerce @@ -131,60 +174,6 @@ services: networks: - ecommerce - # zookeeper: - # image: confluentinc/cp-zookeeper:7.0.1 - # hostname: zookeeper - # container_name: zookeeper - # restart: unless-stopped - # ports: - # - "2181:2181" - # environment: - # ZOOKEEPER_CLIENT_PORT: 2181 - # ZOOKEEPER_TICK_TIME: 2000 - # networks: - # - ecommerce - - # kafka: - # image: confluentinc/cp-kafka:7.0.1 - # hostname: kafka - # container_name: kafka - # restart: unless-stopped - # depends_on: - # - zookeeper - # ports: - # - "9092:9092" - # environment: - # KAFKA_BROKER_ID: 1 - # KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181' - # KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT - # KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 - # KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 - # ADVERTISED_HOST_NAME: kafka - # KAFKA_ADVERTISED_HOSTNAME: 127.0.0.1 - # networks: - # - ecommerce - - # kafka-ui: - # image: provectuslabs/kafka-ui - # container_name: kafka-ui - # ports: - # - "8080:8080" - # restart: always - # environment: - # - KAFKA_CLUSTERS_0_NAME=local - # - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:9092 - # - KAFKA_CLUSTERS_0_ZOOKEEPER=zookeeper:2181 - - # kafdrop: - # image: obsidiandynamics/kafdrop - # container_name: kafdrop - # ports: - # - '9000:9000' - # environment: - # - 'KAFKA_BROKERCONNECT=' - # - 'JVM_OPTS=-Xms32M -Xmx64M' - # - SERVER_SERVLET_CONTEXTPATH=/ - mongo: image: mongo pull_policy: if_not_present @@ -231,6 +220,11 @@ services: - "16686:16686" # Jaeger UI port - "4320:4317" # OTLP gRPC default port - for prevent duplicate expose this port that will expose also by `otel-collector` we not expose it on `4317` - `4320` could use by the app through otlptracegrpc - "4321:4318" # OTLP Http default port - for prevent duplicate expose this port that will expose also by `otel-collector` we not expose it on `4318` - `4321` could use by the app through otlptracehttp + healthcheck: + test: [ "CMD", "curl", "-f", "http://localhost:16686" ] + interval: 10s + retries: 3 + timeout: 10s networks: - ecommerce @@ -328,6 +322,60 @@ services: # depends_on: # - elasticsearch + # zookeeper: + # image: confluentinc/cp-zookeeper:7.0.1 + # hostname: zookeeper + # container_name: zookeeper + # restart: unless-stopped + # ports: + # - "2181:2181" + # environment: + # ZOOKEEPER_CLIENT_PORT: 2181 + # ZOOKEEPER_TICK_TIME: 2000 + # networks: + # - ecommerce + + # kafka: + # image: confluentinc/cp-kafka:7.0.1 + # hostname: kafka + # container_name: kafka + # restart: unless-stopped + # depends_on: + # - zookeeper + # ports: + # - "9092:9092" + # environment: + # KAFKA_BROKER_ID: 1 + # KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181' + # KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT + # KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 + # KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + # ADVERTISED_HOST_NAME: kafka + # KAFKA_ADVERTISED_HOSTNAME: 127.0.0.1 + # networks: + # - ecommerce + + # kafka-ui: + # image: provectuslabs/kafka-ui + # container_name: kafka-ui + # ports: + # - "8080:8080" + # restart: always + # environment: + # - KAFKA_CLUSTERS_0_NAME=local + # - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:9092 + # - KAFKA_CLUSTERS_0_ZOOKEEPER=zookeeper:2181 + + # kafdrop: + # image: obsidiandynamics/kafdrop + # container_name: kafdrop + # ports: + # - '9000:9000' + # environment: + # - 'KAFKA_BROKERCONNECT=' + # - 'JVM_OPTS=-Xms32M -Xmx64M' + # - SERVER_SERVLET_CONTEXTPATH=/ + volumes: eventstore-volume-data: eventstore-volume-logs: diff --git a/deployments/docker-compose/docker-compose.infrastructure.yaml b/deployments/docker-compose/docker-compose.infrastructure.yaml index 4644d93e..a3f6b378 100644 --- a/deployments/docker-compose/docker-compose.infrastructure.yaml +++ b/deployments/docker-compose/docker-compose.infrastructure.yaml @@ -1,5 +1,7 @@ # Ref:https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/examples/demo/docker-compose.yaml # https://github.com/open-telemetry/opentelemetry-demo/blob/main/docker-compose.yml +# https://github.com/grafana/tempo/blob/main/example/docker-compose/local/docker-compose.yaml +# https://github.com/build-on-aws/instrumenting-java-apps-using-opentelemetry/blob/main/docker-compose.yaml version: "3.8" name: go-ecommerce-microservices @@ -32,8 +34,14 @@ services: - ${PROMETHEUS_HOST_PORT:-9090}:${PROMETHEUS_PORT:-9090} command: - --config.file=/etc/prometheus/prometheus.yml + - --web.enable-remote-write-receiver + - --enable-feature=exemplar-storage volumes: - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro + healthcheck: + interval: 5s + retries: 10 + test: wget --no-verbose --tries=1 --spider http://localhost:9090/status || exit 1 networks: - ecommerce @@ -56,11 +64,57 @@ services: restart: unless-stopped volumes: - ./monitoring/grafana.yaml:/etc/grafana/provisioning/datasources/datasource.yaml + - ./monitoring/grafana-bootstrap.ini:/etc/grafana/grafana.ini ports: - ${GRAFANA_HOST_PORT:-3000}:${GRAFANA_PORT:-3000} + environment: + - GF_AUTH_ANONYMOUS_ENABLED=true + - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin + - GF_AUTH_DISABLE_LOGIN_FORM=true + - GF_FEATURE_TOGGLES_ENABLE=traceqlEditor + healthcheck: + interval: 5s + retries: 10 + test: wget --no-verbose --tries=1 --spider http://localhost:3000 || exit 1 + depends_on: + prometheus: + condition: service_healthy + tempo: + condition: service_healthy + networks: + - ecommerce + + # https://grafana.com/docs/tempo/latest/getting-started/ + # https://github.com/grafana/tempo/blob/main/example/docker-compose/local/docker-compose.yaml + # https://github.com/Domoryonok/tracing_demo/blob/master/grafana/docker-compose.yaml + # https://grafana.com/docs/grafana/latest/datasources/jaeger/ + # https://grafana.com/docs/tempo/latest/operations/architecture/ + tempo: + image: grafana/tempo:latest + command: [ "-search.enabled=true", "-config.file=/etc/tempo.yaml" ] + volumes: + - ./otelcollector/tempo.yaml:/etc/tempo.yaml + - ./tempo-data:/tmp/tempo + ports: + - "3200:3200" # tempo UI + - "4322:4317" # otlp grpc + - "9411" # zipkin - export zipkin traces to tempo + - "14268" # jaeger - export jaeger traces to tempo + healthcheck: + interval: 5s + retries: 10 + test: wget --no-verbose --tries=1 --spider http://localhost:3200/status || exit 1 networks: - ecommerce +# k6-tracing: +# image: ghcr.io/grafana/xk6-client-tracing:latest +# environment: +# - ENDPOINT=tempo:4317 +# restart: always +# depends_on: +# - tempo + postgres: image: postgres:latest pull_policy: if_not_present @@ -87,60 +141,6 @@ services: networks: - ecommerce - # zookeeper: - # image: confluentinc/cp-zookeeper:7.0.1 - # hostname: zookeeper - # container_name: zookeeper - # restart: unless-stopped - # ports: - # - "2181:2181" - # environment: - # ZOOKEEPER_CLIENT_PORT: 2181 - # ZOOKEEPER_TICK_TIME: 2000 - # networks: - # - ecommerce - - # kafka: - # image: confluentinc/cp-kafka:7.0.1 - # hostname: kafka - # container_name: kafka - # restart: unless-stopped - # depends_on: - # - zookeeper - # ports: - # - "9092:9092" - # environment: - # KAFKA_BROKER_ID: 1 - # KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181' - # KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT - # KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 - # KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 - # ADVERTISED_HOST_NAME: kafka - # KAFKA_ADVERTISED_HOSTNAME: 127.0.0.1 - # networks: - # - ecommerce - - # kafka-ui: - # image: provectuslabs/kafka-ui - # container_name: kafka-ui - # ports: - # - "8080:8080" - # restart: always - # environment: - # - KAFKA_CLUSTERS_0_NAME=local - # - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:9092 - # - KAFKA_CLUSTERS_0_ZOOKEEPER=zookeeper:2181 - - # kafdrop: - # image: obsidiandynamics/kafdrop - # container_name: kafdrop - # ports: - # - '9000:9000' - # environment: - # - 'KAFKA_BROKERCONNECT=' - # - 'JVM_OPTS=-Xms32M -Xmx64M' - # - SERVER_SERVLET_CONTEXTPATH=/ - mongo: image: mongo pull_policy: if_not_present @@ -187,6 +187,11 @@ services: - "16686:16686" # Jaeger UI port - "4320:4317" # OTLP gRPC default port - for prevent duplicate expose this port that will expose also by `otel-collector` we not expose it on `4317` - `4320` could use by the app through otlptracegrpc - "4321:4318" # OTLP Http default port - for prevent duplicate expose this port that will expose also by `otel-collector` we not expose it on `4318` - `4321` could use by the app through otlptracehttp + healthcheck: + test: [ "CMD", "curl", "-f", "http://localhost:16686" ] + interval: 10s + retries: 3 + timeout: 10s networks: - ecommerce @@ -302,6 +307,61 @@ services: # depends_on: # - elasticsearch + + # zookeeper: + # image: confluentinc/cp-zookeeper:7.0.1 + # hostname: zookeeper + # container_name: zookeeper + # restart: unless-stopped + # ports: + # - "2181:2181" + # environment: + # ZOOKEEPER_CLIENT_PORT: 2181 + # ZOOKEEPER_TICK_TIME: 2000 + # networks: + # - ecommerce + + # kafka: + # image: confluentinc/cp-kafka:7.0.1 + # hostname: kafka + # container_name: kafka + # restart: unless-stopped + # depends_on: + # - zookeeper + # ports: + # - "9092:9092" + # environment: + # KAFKA_BROKER_ID: 1 + # KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181' + # KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT + # KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 + # KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + # ADVERTISED_HOST_NAME: kafka + # KAFKA_ADVERTISED_HOSTNAME: 127.0.0.1 + # networks: + # - ecommerce + + # kafka-ui: + # image: provectuslabs/kafka-ui + # container_name: kafka-ui + # ports: + # - "8080:8080" + # restart: always + # environment: + # - KAFKA_CLUSTERS_0_NAME=local + # - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:9092 + # - KAFKA_CLUSTERS_0_ZOOKEEPER=zookeeper:2181 + + # kafdrop: + # image: obsidiandynamics/kafdrop + # container_name: kafdrop + # ports: + # - '9000:9000' + # environment: + # - 'KAFKA_BROKERCONNECT=' + # - 'JVM_OPTS=-Xms32M -Xmx64M' + # - SERVER_SERVLET_CONTEXTPATH=/ + volumes: eventstore-volume-data: eventstore-volume-logs: diff --git a/deployments/docker-compose/monitoring/grafana-bootstrap.ini b/deployments/docker-compose/monitoring/grafana-bootstrap.ini new file mode 100644 index 00000000..21b3cdbd --- /dev/null +++ b/deployments/docker-compose/monitoring/grafana-bootstrap.ini @@ -0,0 +1,2 @@ +[feature_toggles] +enable = tempoSearch tempoBackendSearch diff --git a/deployments/docker-compose/monitoring/grafana.yaml b/deployments/docker-compose/monitoring/grafana.yaml index 47f0245a..0290ca02 100644 --- a/deployments/docker-compose/monitoring/grafana.yaml +++ b/deployments/docker-compose/monitoring/grafana.yaml @@ -1,16 +1,50 @@ apiVersion: 1 datasources: + # showing Prometheus as one of dashboard tabs - name: Prometheus type: prometheus + uid: prometheus url: http://prometheus:9090 isDefault: true access: proxy editable: true + jsonData: + httpMethod: GET - # Jaeger UI port + # showing Jaeger as one of dashboard tabs - name: Jaeger type: jaeger url: http://jaeger:16686 access: proxy editable: true + +# # showing Tempo as one of dashboard tabs +# # https://github.com/grafana/tempo/blob/main/example/docker-compose/shared/grafana-datasources.yaml#L16 +# - name: Tempo +# type: tempo +# access: proxy +# orgId: 1 +# url: http://tempo:3200 +# basicAuth: false +# isDefault: true +# version: 1 +# editable: false +# apiVersion: 1 +# uid: tempo +# jsonData: +# httpMethod: GET +# serviceMap: +# datasourceUid: prometheus + +# # showing Loki as one of dashboard tabs +# - name: loki +# type: loki +# uid: my-loki +# access: proxy +# orgId: 1 +# url: http://loki:3100 +# basicAuth: false +# isDefault: false +# version: 1 +# editable: true diff --git a/deployments/docker-compose/monitoring/prometheus.yml b/deployments/docker-compose/monitoring/prometheus.yml index d63262dd..582ba0f4 100644 --- a/deployments/docker-compose/monitoring/prometheus.yml +++ b/deployments/docker-compose/monitoring/prometheus.yml @@ -57,9 +57,16 @@ scrape_configs: static_configs: - targets: ['cadvisor:8080'] - # OpenTelemetry collector - - job_name: 'otel-collector' - scrape_interval: 10s +# # scrap exported metrics by otel-collector +# # OpenTelemetry collector +# - job_name: 'otel-collector' +# scrape_interval: 10s +# static_configs: +# - targets: ['otel-collector:8889'] +# - targets: ['otel-collector:8888'] + + # internal metrics by tempo + # https://github.com/grafana/tempo/blob/main/example/docker-compose/shared/prometheus.yaml + - job_name: 'tempo' static_configs: - - targets: ['otel-collector:8889'] - - targets: ['otel-collector:8888'] + - targets: [ 'tempo:3200' ] diff --git a/deployments/docker-compose/otelcollector/otelcol-config.yml b/deployments/docker-compose/otelcollector/otelcol-config.yml index c16683d7..68533ee2 100644 --- a/deployments/docker-compose/otelcollector/otelcol-config.yml +++ b/deployments/docker-compose/otelcollector/otelcol-config.yml @@ -3,6 +3,7 @@ # Ref: https://github.com/open-telemetry/opentelemetry-demo/blob/main/src/otelcollector/otelcol-observability.yml # https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/examples/demo/otel-collector-config.yaml +# https://www.youtube.com/watch?v=EeU-k659lpw receivers: otlp: @@ -50,4 +51,4 @@ service: metrics: receivers: [otlp] processors: [batch] - exporters: [logging, prometheus] \ No newline at end of file + exporters: [logging, prometheus] diff --git a/deployments/docker-compose/otelcollector/tempo.yaml b/deployments/docker-compose/otelcollector/tempo.yaml new file mode 100644 index 00000000..743ef05d --- /dev/null +++ b/deployments/docker-compose/otelcollector/tempo.yaml @@ -0,0 +1,57 @@ +# https://github.com/grafana/tempo/blob/main/example/docker-compose/shared/tempo.yaml + +server: + http_listen_port: 3200 + +query_frontend: + search: + duration_slo: 5s + throughput_bytes_slo: 1.073741824e+09 + trace_by_id: + duration_slo: 5s + +distributor: + receivers: # this configuration will listen on all ports and protocols that tempo is capable of. + jaeger: # the receives all come from the OpenTelemetry collector. more configuration information can + protocols: # be found there: https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver + thrift_http: # + grpc: # for a production deployment you should only enable the receivers you need! + thrift_binary: + thrift_compact: + zipkin: + otlp: + protocols: + http: + grpc: + opencensus: + +ingester: + max_block_duration: 5m # cut the headblock when this much time passes. this is being set for demo purposes and should probably be left alone normally + +compactor: + compaction: + block_retention: 1h # overall Tempo trace retention. set for demo purposes + +metrics_generator: + registry: + external_labels: + source: tempo + cluster: docker-compose + storage: + path: /tmp/tempo/generator/wal + remote_write: + - url: http://prometheus:9090/api/v1/write + send_exemplars: true + +storage: + trace: + backend: local # backend configuration to use + wal: + path: /tmp/tempo/wal # where to store the the wal locally + local: + path: /tmp/tempo/blocks + +overrides: + defaults: + metrics_generator: + processors: [service-graphs, span-metrics] # enables metrics generator diff --git a/internal/pkg/go.mod b/internal/pkg/go.mod index 2ace5837..c38be9da 100644 --- a/internal/pkg/go.mod +++ b/internal/pkg/go.mod @@ -16,7 +16,7 @@ require ( github.com/doug-martin/goqu/v9 v9.18.0 github.com/elastic/go-elasticsearch/v8 v8.10.0 github.com/go-playground/validator v9.31.0+incompatible - github.com/go-resty/resty/v2 v2.8.0 + github.com/go-resty/resty/v2 v2.9.1 github.com/go-testfixtures/testfixtures/v3 v3.9.0 github.com/goccy/go-json v0.10.2 github.com/goccy/go-reflect v1.2.0 @@ -38,44 +38,43 @@ require ( github.com/mitchellh/mapstructure v1.5.0 github.com/nolleh/caption_json_formatter v0.2.2 github.com/onsi/ginkgo/v2 v2.12.1 - github.com/onsi/gomega v1.27.10 + github.com/onsi/gomega v1.28.0 github.com/orlangure/gnomock v0.30.0 github.com/ory/dockertest/v3 v3.10.0 github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 github.com/pressly/goose/v3 v3.15.0 - github.com/prometheus/client_golang v1.16.0 + github.com/prometheus/client_golang v1.17.0 github.com/rabbitmq/amqp091-go v1.8.1 github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 - github.com/redis/go-redis/v9 v9.2.0 + github.com/redis/go-redis/v9 v9.2.1 github.com/samber/lo v1.38.1 github.com/satori/go.uuid v1.2.0 github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.16.0 github.com/stretchr/testify v1.8.4 - github.com/testcontainers/testcontainers-go v0.24.1 - github.com/testcontainers/testcontainers-go/modules/postgres v0.24.1 + github.com/testcontainers/testcontainers-go v0.25.0 + github.com/testcontainers/testcontainers-go/modules/postgres v0.25.0 github.com/uptrace/bun v1.1.16 github.com/uptrace/bun/dialect/pgdialect v1.1.16 github.com/uptrace/bun/driver/pgdriver v1.1.16 - github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2 - github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 + github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.3 + github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3 go.mongodb.org/mongo-driver v1.12.1 - go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 - go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 - go.opentelemetry.io/contrib/instrumentation/host v0.44.0 - go.opentelemetry.io/contrib/propagators/ot v1.19.0 - go.opentelemetry.io/otel v1.18.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 - go.opentelemetry.io/otel/exporters/prometheus v0.41.0 - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 - go.opentelemetry.io/otel/exporters/zipkin v1.18.0 - go.opentelemetry.io/otel/metric v1.18.0 - go.opentelemetry.io/otel/sdk v1.18.0 - go.opentelemetry.io/otel/sdk/metric v0.41.0 - go.opentelemetry.io/otel/trace v1.18.0 + go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.45.0 + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0 + go.opentelemetry.io/contrib/instrumentation/host v0.45.0 + go.opentelemetry.io/contrib/propagators/ot v1.20.0 + go.opentelemetry.io/otel v1.19.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 + go.opentelemetry.io/otel/exporters/prometheus v0.42.0 + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 + go.opentelemetry.io/otel/exporters/zipkin v1.19.0 + go.opentelemetry.io/otel/metric v1.19.0 + go.opentelemetry.io/otel/sdk v1.19.0 + go.opentelemetry.io/otel/sdk/metric v1.19.0 + go.opentelemetry.io/otel/trace v1.19.0 go.uber.org/fx v1.20.0 go.uber.org/zap v1.26.0 google.golang.org/grpc v1.58.2 @@ -121,7 +120,7 @@ require ( github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 // indirect + github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect @@ -166,13 +165,13 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect - github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/segmentio/asm v1.2.0 // indirect - github.com/shirou/gopsutil/v3 v3.23.8 // indirect + github.com/shirou/gopsutil/v3 v3.23.9 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/spf13/afero v1.10.0 // indirect @@ -185,10 +184,10 @@ require ( github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect - github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 // indirect + github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect - github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.0 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect @@ -198,8 +197,8 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/dig v1.17.0 // indirect diff --git a/internal/pkg/go.sum b/internal/pkg/go.sum index 0b331477..5c06607e 100644 --- a/internal/pkg/go.sum +++ b/internal/pkg/go.sum @@ -203,8 +203,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator v9.31.0+incompatible h1:UA72EPEogEnq76ehGdEDp4Mit+3FDh548oRqwVgNsHA= github.com/go-playground/validator v9.31.0+incompatible/go.mod h1:yrEkQXlcI+PugkyDjY2bRrL/UBU4f3rvrgkN3V8JEig= -github.com/go-resty/resty/v2 v2.8.0 h1:J29d0JFWwSWrDCysnOK/YjsPMLQTx0TvgJEHVGvf2L8= -github.com/go-resty/resty/v2 v2.8.0/go.mod h1:UCui0cMHekLrSntoMyofdSTaPpinlRHFtPpizuyDW2w= +github.com/go-resty/resty/v2 v2.9.1 h1:PIgGx4VrHvag0juCJ4dDv3MiFRlDmP0vicBucwf+gLM= +github.com/go-resty/resty/v2 v2.9.1/go.mod h1:4/GYJVjh9nhkhGR6AUNW3XhpDYNUr+Uvy9gV/VGZIy4= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= @@ -297,8 +297,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 h1:gpptm606MZYGaMHMsB4Srmb6EbW/IVHnt04rcMXnkBQ= -github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ= +github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -496,8 +496,8 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/ginkgo/v2 v2.12.1 h1:uHNEO1RP2SpuZApSkel9nEh1/Mu+hmQe7Q+Pepg5OYA= github.com/onsi/ginkgo/v2 v2.12.1/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/onsi/gomega v1.28.0 h1:i2rg/p9n/UqIDAMFUJ6qIUUMcsqOuUHgbpbu235Vr1c= +github.com/onsi/gomega v1.28.0/go.mod h1:A1H2JE76sI14WIP57LMKj7FVfCHx3g3BcZVjJG8bjX8= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -539,11 +539,11 @@ github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3g github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/pressly/goose/v3 v3.15.0 h1:6tY5aDqFknY6VZkorFGgZtWygodZQxfmmEF4rqyJW9k= github.com/pressly/goose/v3 v3.15.0/go.mod h1:LlIo3zGccjb/YUgG+Svdb9Er14vefRdlDI7URCDrwYo= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= @@ -556,8 +556,8 @@ github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ= github.com/redis/go-redis/v9 v9.0.3/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= -github.com/redis/go-redis/v9 v9.2.0 h1:zwMdX0A4eVzse46YN18QhuDiM4uf3JmkOB4VZrdt5uI= -github.com/redis/go-redis/v9 v9.2.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= +github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -578,8 +578,8 @@ github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7 github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= -github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= -github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/shirou/gopsutil/v3 v3.23.9 h1:ZI5bWVeu2ep4/DIxB4U9okeYJ7zp/QLTO4auRb/ty/E= +github.com/shirou/gopsutil/v3 v3.23.9/go.mod h1:x/NWSb71eMcjFIO0vhyGW5nZ7oSIgVjrCnADckb85GA= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= @@ -633,10 +633,10 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/testcontainers/testcontainers-go v0.24.1 h1:gJdZuQIVWnMJTo+CmQMEP7/CAagNk/0jbcUPn3OWvD8= -github.com/testcontainers/testcontainers-go v0.24.1/go.mod h1:MGBiAkCm86yXQoCiipmQCqZLVdk1uFqtMqaU1Or0MRk= -github.com/testcontainers/testcontainers-go/modules/postgres v0.24.1 h1:lSJLORAjkj8PoiZef+KoziJbhpRmL1ELzJXQQ8L3s1U= -github.com/testcontainers/testcontainers-go/modules/postgres v0.24.1/go.mod h1:QG4rCYFma/K7CbAFtrqCIn87EI6bNRWaW+Ebt4UV2WA= +github.com/testcontainers/testcontainers-go v0.25.0 h1:erH6cQjsaJrH+rJDU9qIf89KFdhK0Bft0aEZHlYC3Vs= +github.com/testcontainers/testcontainers-go v0.25.0/go.mod h1:4sC9SiJyzD1XFi59q8umTQYWxnkweEc5OjVtTUlJzqQ= +github.com/testcontainers/testcontainers-go/modules/postgres v0.25.0 h1:8WNK1Edo9ohRYPrDCXWdoVY2cbg/oFh9y5uWZGSBESo= +github.com/testcontainers/testcontainers-go/modules/postgres v0.25.0/go.mod h1:XpwOhyUXheL31hz73L8be8maW1rQq8H48x5qZeHtYr0= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= @@ -650,12 +650,12 @@ github.com/uptrace/bun/dialect/pgdialect v1.1.16 h1:eUPZ+YCJ69BA+W1X1ZmpOJSkv1oY github.com/uptrace/bun/dialect/pgdialect v1.1.16/go.mod h1:KQjfx/r6JM0OXfbv0rFrxAbdkPD7idK8VitnjIV9fZI= github.com/uptrace/bun/driver/pgdriver v1.1.16 h1:b/NiSXk6Ldw7KLfMLbOqIkm4odHd7QiNOCPLqPFJjK4= github.com/uptrace/bun/driver/pgdriver v1.1.16/go.mod h1:Rmfbc+7lx1z/umjMyAxkOHK81LgnGj71XC5YpA6k1vU= -github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2 h1:s3quVevwQlgEMCkvscS/VHo92amtyMzRfcuOZqfevrM= -github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2/go.mod h1:IJLBT7ItgUACTEoq6BEw/9HwHWL4BiPirYgKhZS83Lg= -github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 h1:CNznWHkrbA6o1q2H/BsH4tIHf4zbKNtndeoV+AH8z0U= -github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2/go.mod h1:7YSrHCmYPHIXjTWnKSU7EGT0TFEcm3WwSeQquwCGg38= -github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 h1:uyrW06oJi4iWvhjPLVfk4qrSP2Zm0AMozKKDmp6i4pE= -github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2/go.mod h1:PMAs2dNxP55lgt6xu0if+Jasm6s+Xpmqn6ev1NyDfnI= +github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.3 h1:m5eNyOhch/7tyK6aN6eRRpNoD1vM8PNh64dA05X22Js= +github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.3/go.mod h1:APPUXm9BbpH7NFkfpbw04raZSitzl19/3NOCu0rbI4E= +github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3 h1:LyGS9cIZV0YVhE81zwfMhIE2l2flcj3wn5IoK4VkbWA= +github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3/go.mod h1:RvCYhPchLhvQ9l9C9goblbgO7BaKt597kBMf5mgKyo0= +github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3 h1:2na5W81H38Z4qXCQCuzlcdSMiTWgPJ6XeZIArq6VIJE= +github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3/go.mod h1:9IVEh9mPv3NwFf99dVLX15FqVgdpZJ8RMDo/Cr0vK74= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -664,8 +664,8 @@ github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQ github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= -github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/msgpack/v5 v5.4.0 h1:hRM0digJwyR6vll33NNAwCFguy5JuBD6jxDmQP3l608= +github.com/vmihailenco/msgpack/v5 v5.4.0/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= @@ -708,44 +708,40 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 h1:9n9+SOwuCyZ0L8SbQYjZ5H+GKojHN3Kl8pBLwBUQqhk= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0/go.mod h1:Wa9/q2K5L+ftWke2iekGNqVzwBWqyhI5OhtHKU7Qe04= -go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 h1:M5oKw7m89PAciR2j41n5Zq9rShK14iUadvCRy7nkSIo= -go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0/go.mod h1:JH6FxBlkXo/cYoU/m65W5dOQ6sqPL+jHtSJaSE7/+XQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 h1:b8xjZxHbLrXAum4SxJd1Rlm7Y/fKaB+6ACI7/e5EfSA= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0/go.mod h1:1ei0a32xOGkFoySu7y1DAHfcuIhC0pNZpvY2huXuMy4= -go.opentelemetry.io/contrib/instrumentation/host v0.44.0 h1:SNqDjPpQmwFYvDipyJJxDbU5zKNWiYSMii864ubzIuQ= -go.opentelemetry.io/contrib/instrumentation/host v0.44.0/go.mod h1:bZcqg3yy0riQLNkx8dJWV4J3tbfL+6LQ5lIbI+vmarE= -go.opentelemetry.io/contrib/propagators/b3 v1.19.0 h1:ulz44cpm6V5oAeg5Aw9HyqGFMS6XM7untlMEhD7YzzA= -go.opentelemetry.io/contrib/propagators/b3 v1.19.0/go.mod h1:OzCmE2IVS+asTI+odXQstRGVfXQ4bXv9nMBRK0nNyqQ= -go.opentelemetry.io/contrib/propagators/ot v1.19.0 h1:vODRLMlKN4ApM8ri0UDk8nnEeISuwxpf67sE7PmOHhE= -go.opentelemetry.io/contrib/propagators/ot v1.19.0/go.mod h1:S2Uc7th2ZmLiHu0lrCmDCgTQ/y5Nbbis+TNjR1jjm4Q= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 h1:k0k7hFNDd8K4iOMJXj7s8sHaC4mhTlAeppRmZXLgZ6k= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 h1:HgbDTD8pioFdY3NRc/YCvsWjqQPtweGyXxa32LgnTOw= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0/go.mod h1:tmvt/yK5Es5d6lHYWerLSOna8lCEfrBVX/a9M0ggqss= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 h1:IAtl+7gua134xcV3NieDhJHjjOVeJhXAnYf/0hswjUY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0/go.mod h1:w+pXobnBzh95MNIkeIuAKcHe/Uu/CX2PKIvBP6ipKRA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32ay7mJG2leczfREEhoW3VfSZIvHaB+gvVo1o8DQ8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 h1:XzjGkawtAXs20Y+s6k1GNDMBsMDOV28TOT8cxmE42qM= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0/go.mod h1:HAomEgjcKZk3VJ+HHdHLnhZXeGqdzPxxNTdKYRopUXY= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes= -go.opentelemetry.io/otel/exporters/zipkin v1.18.0 h1:ZqrHgvega5NIiScTiVrtpZSpEmjUdwzkhuuCEIMAp+s= -go.opentelemetry.io/otel/exporters/zipkin v1.18.0/go.mod h1:C80yIYcSceQipAZb4Ah11EE/yERlyc1MtqJG2xP7p+s= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.45.0 h1:bldpPC7XAv7f7LKTwNfRkNdzRhjtXaWybZFFa16dAb8= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.45.0/go.mod h1:xhkNpJG3D+kmuaciNTco7cdK27Fb77J9Iqcq5CMe4Y8= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0 h1:RsQi0qJ2imFfCvZabqzM9cNXBG8k6gXMv1A0cXRmH6A= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0/go.mod h1:vsh3ySueQCiKPxFLvjWC4Z135gIa34TQ/NSqkDTZYUM= +go.opentelemetry.io/contrib/instrumentation/host v0.45.0 h1:1uzNKJDqZ6y6F5J6aKWgJjRREpKiGhBvKHlWon/bqB4= +go.opentelemetry.io/contrib/instrumentation/host v0.45.0/go.mod h1:vlqPvzDsmB4+jlERxBRXsdLCD6Q0LoBzxHqNXp3qvG4= +go.opentelemetry.io/contrib/propagators/ot v1.20.0 h1:duH7mgL6VGQH7e7QEAVOFkCQXWpCb4PjTtrhdrYrJRQ= +go.opentelemetry.io/contrib/propagators/ot v1.20.0/go.mod h1:gijQzxOq0JLj9lyZhTvqjDddGV/zaNagpPIn+2r8CEI= +go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= +go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 h1:NmnYCiR0qNufkldjVvyQfZTHSdzeHoZ41zggMsdMcLM= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0/go.mod h1:UVAO61+umUsHLtYb8KXXRoHtxUkdOPkYidzW3gipRLQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0 h1:jwV9iQdvp38fxXi8ZC+lNpxjK16MRcZlpDYvbuO1FiA= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0/go.mod h1:f3bYiqNqhoPxkvI2LrXqQVC546K7BuRDL/kKuxkujhA= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0 h1:4jJuoeOo9W6hZnz+r046fyoH5kykZPRvKfUXJVfMpB0= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0/go.mod h1:/MtYTE1SfC2QIcE0bDot6fIX+h+WvXjgTqgn9P0LNPE= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 h1:Nw7Dv4lwvGrI68+wULbcq7su9K2cebeCUrDjVrUJHxM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0/go.mod h1:1MsF6Y7gTqosgoZvHlzcaaM8DIMNZgJh87ykokoNH7Y= +go.opentelemetry.io/otel/exporters/zipkin v1.19.0 h1:EGY0h5mGliP9o/nIkVuLI0vRiQqmsYOcbwCuotksO1o= +go.opentelemetry.io/otel/exporters/zipkin v1.19.0/go.mod h1:JQgTGJP11yi3o4GHzIWYodhPisxANdqxF1eHwDSnJrI= +go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= +go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k= +go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY= +go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= +go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -999,6 +995,7 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/internal/pkg/grpc/client.go b/internal/pkg/grpc/client.go index 54fc3ecd..c413be98 100644 --- a/internal/pkg/grpc/client.go +++ b/internal/pkg/grpc/client.go @@ -5,8 +5,10 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/handlers" "emperror.dev/errors" + "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "google.golang.org/grpc" "google.golang.org/grpc/connectivity" "google.golang.org/grpc/credentials/insecure" @@ -29,6 +31,10 @@ func NewGrpcClient(config *config.GrpcOptions) (GrpcClient, error) { // https://github.com/open-telemetry/opentelemetry-go-contrib/blob/df16f32df86b40077c9c90d06f33c4cdb6dd5afa/instrumentation/google.golang.org/grpc/otelgrpc/example_interceptor_test.go conn, err := grpc.Dial(fmt.Sprintf("%s%s", config.Host, config.Port), grpc.WithTransportCredentials(insecure.NewCredentials()), + // https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/example/client/main.go#L47C3-L47C52 + // https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/doc.go + grpc.WithStatsHandler(otelgrpc.NewClientHandler()), + grpc.WithStatsHandler(handlers.NewClientHandler()), ) if err != nil { return nil, err @@ -57,7 +63,10 @@ func (g *grpcClient) WaitForAvailableConnection() error { return err } -func waitUntilConditionMet(conditionToMet func() bool, timeout ...time.Duration) error { +func waitUntilConditionMet( + conditionToMet func() bool, + timeout ...time.Duration, +) error { timeOutTime := 20 * time.Second if len(timeout) >= 0 && timeout != nil { timeOutTime = timeout[0] @@ -68,7 +77,9 @@ func waitUntilConditionMet(conditionToMet func() bool, timeout ...time.Duration) meet := conditionToMet() for meet == false { if timeOutExpired { - return errors.New("grpc connection could not be established in the given timeout.") + return errors.New( + "grpc connection could not be established in the given timeout.", + ) } time.Sleep(time.Second * 2) meet = conditionToMet() diff --git a/internal/pkg/grpc/grpcErrors/grpc_error_parser.go b/internal/pkg/grpc/grpcErrors/grpc_error_parser.go index 1c5b7686..be8a55d4 100644 --- a/internal/pkg/grpc/grpcErrors/grpc_error_parser.go +++ b/internal/pkg/grpc/grpcErrors/grpc_error_parser.go @@ -21,14 +21,26 @@ func ParseError(err error) GrpcErr { var validatorErr validator.ValidationErrors stackTrace := errorUtils.ErrorsWithStack(err) - if err != nil { + if err != nil && customErr != nil { switch { case customErrors.IsDomainError(err, customErr.Status()): - return NewDomainGrpcError(codes.Code(customErr.Status()), customErr.Error(), stackTrace) + return NewDomainGrpcError( + codes.Code(customErr.Status()), + customErr.Error(), + stackTrace, + ) case customErrors.IsApplicationError(err, customErr.Status()): - return NewApplicationGrpcError(codes.Code(customErr.Status()), customErr.Error(), stackTrace) + return NewApplicationGrpcError( + codes.Code(customErr.Status()), + customErr.Error(), + stackTrace, + ) case customErrors.IsApiError(err, customErr.Status()): - return NewApiGrpcError(codes.Code(customErr.Status()), customErr.Error(), stackTrace) + return NewApiGrpcError( + codes.Code(customErr.Status()), + customErr.Error(), + stackTrace, + ) case customErrors.IsBadRequestError(err): return NewBadRequestGrpcError(customErr.Error(), stackTrace) case customErrors.IsNotFoundError(err): @@ -54,14 +66,22 @@ func ParseError(err error) GrpcErr { return NewInternalServerGrpcError(customErr.Error(), stackTrace) case customErrors.IsMarshalingError(err): return NewInternalServerGrpcError(customErr.Error(), stackTrace) + default: + return NewInternalServerGrpcError(err.Error(), stackTrace) + } + } else if err != nil && customErr == nil { + switch { case errors.Is(err, sql.ErrNoRows): return NewNotFoundErrorGrpcError(err.Error(), stackTrace) case errors.Is(err, context.DeadlineExceeded): - return NewGrpcError(codes.DeadlineExceeded, constants.ErrRequestTimeoutTitle, err.Error(), stackTrace) + return NewGrpcError( + codes.DeadlineExceeded, + constants.ErrRequestTimeoutTitle, + err.Error(), + stackTrace, + ) case errors.As(err, &validatorErr): return NewValidationGrpcError(validatorErr.Error(), stackTrace) - default: - return NewInternalServerGrpcError(err.Error(), stackTrace) } } diff --git a/internal/pkg/grpc/grpc_fx.go b/internal/pkg/grpc/grpc_fx.go index de18d57a..8c388b1c 100644 --- a/internal/pkg/grpc/grpc_fx.go +++ b/internal/pkg/grpc/grpc_fx.go @@ -12,7 +12,11 @@ import ( var ( // Module provided to fxlog // https://uber-go.github.io/fx/modules.html - Module = fx.Module("grpcfx", grpcProviders, grpcInvokes) //nolint:gochecknoglobals + Module = fx.Module( + "grpcfx", + grpcProviders, + grpcInvokes, + ) //nolint:gochecknoglobals // - order is not important in provide // - provide can have parameter and will resolve if registered @@ -23,7 +27,7 @@ var ( // https://uber-go.github.io/fx/annotate.html fx.Annotate( NewGrpcServer, - fx.ParamTags(``, ``, `optional:"true"`), + fx.ParamTags(``, ``), ), NewGrpcClient, )) @@ -52,7 +56,10 @@ func registerHooks( // if (ctx.Err() == nil), context not canceled or deadlined if err := grpcServer.RunGrpcServer(nil); err != nil { // do a fatal for going to OnStop process - logger.Fatalf("(GrpcServer.RunGrpcServer) error in running server: {%v}", err) + logger.Fatalf( + "(GrpcServer.RunGrpcServer) error in running server: {%v}", + err, + ) } }() logger.Infof( diff --git a/internal/pkg/grpc/handlers/config.go b/internal/pkg/grpc/handlers/config.go new file mode 100644 index 00000000..aba9c85e --- /dev/null +++ b/internal/pkg/grpc/handlers/config.go @@ -0,0 +1,80 @@ +package handlers + +import ( + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/trace" +) + +// ref: https://github.com/bakins/otel-grpc-statshandler/blob/main/statshandler.go + +// Option applies an option value when creating a Handler. +type Option interface { + apply(*config) +} + +type optionFunc func(*config) + +func (f optionFunc) apply(c *config) { + f(c) +} + +type config struct { + metricsProvider metric.MeterProvider + tracerProvider trace.TracerProvider + propagator propagation.TextMapPropagator + Namespace string + serviceName string + instrumentationName string +} + +var defualtConfig = config{ + metricsProvider: otel.GetMeterProvider(), + tracerProvider: otel.GetTracerProvider(), + propagator: otel.GetTextMapPropagator(), + serviceName: "application", + instrumentationName: "grpc-otel", +} + +func WithMeterProvider(m metric.MeterProvider) Option { + return optionFunc(func(c *config) { + c.metricsProvider = m + }) +} + +func WithTraceProvider(t trace.TracerProvider) Option { + return optionFunc(func(c *config) { + c.tracerProvider = t + }) +} + +func WithPropagators(p propagation.TextMapPropagator) Option { + return optionFunc(func(c *config) { + c.propagator = p + }) +} + +func SetNamespace(v string) Option { + return optionFunc(func(cfg *config) { + if cfg.Namespace != "" { + cfg.Namespace = v + } + }) +} + +func SetServiceName(v string) Option { + return optionFunc(func(cfg *config) { + if cfg.serviceName != "" { + cfg.serviceName = v + } + }) +} + +func SetInstrumentationName(v string) Option { + return optionFunc(func(cfg *config) { + if cfg.instrumentationName != "" { + cfg.instrumentationName = v + } + }) +} diff --git a/internal/pkg/grpc/handlers/handler.go b/internal/pkg/grpc/handlers/handler.go new file mode 100644 index 00000000..09e2672f --- /dev/null +++ b/internal/pkg/grpc/handlers/handler.go @@ -0,0 +1,327 @@ +package handlers + +import ( + "context" + "fmt" + "strings" + "time" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/propagation" + semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + "go.opentelemetry.io/otel/trace" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/stats" + "google.golang.org/grpc/status" +) + +// ref: https://github.com/bakins/otel-grpc-statshandler/blob/main/statshandler.go +// https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/config.go +// https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/stats_handler.go +// https://github.com/open-telemetry/opentelemetry-go/blob/main/example/prometheus/main.go#L52 + +// https://opentelemetry.io/docs/specs/otel/metrics/semantic_conventions/rpc-metrics/ + +// ServerHandler implements https://pkg.go.dev/google.golang.org/grpc/stats#ServerHandler +// It records OpenTelemetry metrics and traces. +type ServerHandler struct { + handler +} + +// ClientHandler implements https://pkg.go.dev/google.golang.org/grpc/stats#ServerHandler +// It records OpenTelemetry metrics and traces. +type ClientHandler struct { + handler +} + +type gRPCContextKey struct{} + +type gRPCContext struct { + messagesReceived int64 + messagesSent int64 + attributes []attribute.KeyValue + startTime time.Time +} + +type handler struct { + tracer trace.Tracer + meter metric.Meter + propagator propagation.TextMapPropagator + rpcDuration metric.Int64Histogram + rpcRequestSize metric.Int64Histogram + rpcResponseSize metric.Int64Histogram + rpcRequestsPerRPC metric.Int64Histogram + rpcResponsesPerRPC metric.Int64Histogram + rpcTotalFailed metric.Int64Counter + rpcTotalSuccess metric.Int64Counter + spanKind trace.SpanKind + config config +} + +func newHandler(spanKind trace.SpanKind, options []Option) (handler, error) { + c := defualtConfig + + for _, o := range options { + o.apply(&c) + } + + meter := c.metricsProvider.Meter(c.instrumentationName) + + prefix := "rpc.server" + if spanKind == trace.SpanKindClient { + prefix = "rpc.client" + } + + // https://opentelemetry.io/docs/specs/otel/metrics/semantic_conventions/rpc-metrics/#rpc-server + rpcServerDuration, err := meter.Int64Histogram(prefix+".duration", + metric.WithDescription("Measures the duration of inbound RPC."), + metric.WithUnit("ms")) + if err != nil { + otel.Handle(err) + } + + rpcRequestSize, err := meter.Int64Histogram( + prefix+".request.size", + metric.WithDescription( + "Measures size of RPC request messages (uncompressed).", + ), + metric.WithUnit("bytes"), + ) + if err != nil { + return handler{}, err + } + + rpcResponseSize, err := meter.Int64Histogram( + prefix+".response.size", + metric.WithDescription( + "Measures size of RPC response messages (uncompressed)", + ), + metric.WithUnit("bytes"), + ) + if err != nil { + return handler{}, err + } + + rpcRequestsPerRPC, err := meter.Int64Histogram( + prefix+".requests_per_rpc", + metric.WithDescription( + "Measures the number of messages received per RPC. Should be 1 for all non-streaming RPCs", + ), + metric.WithUnit("count"), + ) + if err != nil { + return handler{}, err + } + + rpcResponsesPerRPC, err := meter.Int64Histogram( + prefix+".responses_per_rpc", + metric.WithDescription( + "Measures the number of messages sent per RPC. Should be 1 for all non-streaming RPCs", + ), + metric.WithUnit("count")) + if err != nil { + return handler{}, err + } + + rpcTotalFailed, err := meter.Int64Counter( + fmt.Sprintf("%s_error_grpc_requests_total", c.serviceName), + metric.WithDescription("The total number of error grpc requests"), + metric.WithUnit("count"), + ) + if err != nil { + return handler{}, err + } + + rpcTotalSuccess, err := meter.Int64Counter( + fmt.Sprintf("%s_success_grpc_requests_total", c.serviceName), + metric.WithDescription("The total number of success grpc requests"), + metric.WithUnit("count"), + ) + if err != nil { + return handler{}, err + } + + h := handler{ + tracer: c.tracerProvider.Tracer(c.instrumentationName), + meter: meter, + spanKind: spanKind, + config: c, + rpcDuration: rpcServerDuration, + rpcRequestSize: rpcRequestSize, + rpcResponseSize: rpcResponseSize, + rpcRequestsPerRPC: rpcRequestsPerRPC, + rpcResponsesPerRPC: rpcResponsesPerRPC, + rpcTotalFailed: rpcTotalFailed, + rpcTotalSuccess: rpcTotalSuccess, + } + + return h, nil +} + +func (h *handler) tagRPC( + ctx context.Context, + info *stats.RPCTagInfo, +) context.Context { + ctx = extract(ctx, h.config.propagator) + + var attributes []attribute.KeyValue + attributes = append(attributes, semconv.RPCSystemGRPC) + + parts := strings.Split(info.FullMethodName, "/") + if len(parts) == 3 { + attributes = append(attributes, semconv.RPCServiceKey.String(parts[1])) + attributes = append(attributes, semconv.RPCMethodKey.String(parts[2])) + } + + gctx := gRPCContext{attributes: attributes, startTime: time.Now()} + + return context.WithValue(ctx, gRPCContextKey{}, &gctx) +} + +func (h *handler) handleRPC(ctx context.Context, rs stats.RPCStats) { + _ = trace.SpanFromContext(ctx) + gctx, _ := ctx.Value(gRPCContextKey{}).(*gRPCContext) + + switch rs := rs.(type) { + case *stats.Begin: + case *stats.InPayload: + if gctx != nil { + // https://github.com/open-telemetry/opentelemetry-go/blob/main/example/prometheus/main.go#L52 + opt := metric.WithAttributes(gctx.attributes...) + h.rpcRequestSize.Record(ctx, int64(rs.Length), opt) + } + + case *stats.OutPayload: + if gctx != nil { + // https://github.com/open-telemetry/opentelemetry-go/blob/main/example/prometheus/main.go#L52 + opt := metric.WithAttributes(gctx.attributes...) + h.rpcResponseSize.Record(ctx, int64(rs.Length), opt) + } + case *stats.End: + if rs.Error != nil { + s, _ := status.FromError(rs.Error) + gctx.attributes = append(gctx.attributes, statusCodeAttr(s.Code())) + opt := metric.WithAttributes(gctx.attributes...) + + h.rpcTotalFailed.Add(ctx, 1, opt) + } else { + gctx.attributes = append(gctx.attributes, statusCodeAttr(codes.OK)) + opt := metric.WithAttributes(gctx.attributes...) + + h.rpcTotalSuccess.Add(ctx, 1, opt) + } + + if gctx != nil { + duration := time.Since(gctx.startTime).Milliseconds() + opt := metric.WithAttributes(gctx.attributes...) + + h.rpcDuration.Record( + ctx, + duration, + opt, + ) + + h.rpcRequestsPerRPC.Record( + ctx, + gctx.messagesReceived, + opt, + ) + + h.rpcResponsesPerRPC.Record( + ctx, + gctx.messagesSent, + opt, + ) + } + + default: + return + } +} + +func statusCodeAttr(c codes.Code) attribute.KeyValue { + return semconv.RPCGRPCStatusCodeKey.Int(int(c)) +} + +func NewServerHandler(options ...Option) stats.Handler { + h, err := newHandler(trace.SpanKindServer, options) + if err != nil { + otel.Handle(err) + } + + s := &ServerHandler{ + handler: h, + } + + return s +} + +func NewClientHandler(options ...Option) stats.Handler { + h, err := newHandler(trace.SpanKindClient, options) + if err != nil { + otel.Handle(err) + } + + c := &ClientHandler{ + handler: h, + } + + return c +} + +func (s *ServerHandler) TagRPC( + ctx context.Context, + info *stats.RPCTagInfo, +) context.Context { + return s.handler.tagRPC(ctx, info) +} + +// HandleRPC processes the RPC stats. +func (s *ServerHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) { + s.handler.handleRPC(ctx, rs) +} + +// TagConn can attach some information to the given context. +func (s *ServerHandler) TagConn( + ctx context.Context, + _ *stats.ConnTagInfo, +) context.Context { + // no-op + return ctx +} + +// HandleConn processes the Conn stats. +func (s *ServerHandler) HandleConn(_ context.Context, _ stats.ConnStats) { + // no-op +} + +func (c *ClientHandler) TagRPC( + ctx context.Context, + info *stats.RPCTagInfo, +) context.Context { + return c.handler.tagRPC(ctx, info) +} + +func (c *ClientHandler) HandleRPC( + ctx context.Context, + rpcStats stats.RPCStats, +) { + c.handler.handleRPC(ctx, rpcStats) +} + +func (c *ClientHandler) TagConn( + ctx context.Context, + _ *stats.ConnTagInfo, +) context.Context { + // no-op + return ctx +} + +func (c *ClientHandler) HandleConn( + _ context.Context, + _ stats.ConnStats, +) { + // no-op +} diff --git a/internal/pkg/grpc/handlers/supplier.go b/internal/pkg/grpc/handlers/supplier.go new file mode 100644 index 00000000..4751ca09 --- /dev/null +++ b/internal/pkg/grpc/handlers/supplier.go @@ -0,0 +1,53 @@ +package handlers + +import ( + "context" + + "go.opentelemetry.io/otel/propagation" + "google.golang.org/grpc/metadata" +) + +// https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/metadata_supplier.go#L27 +type metadataSupplier struct { + metadata *metadata.MD +} + +var _ propagation.TextMapCarrier = &metadataSupplier{} + +func (s *metadataSupplier) Get(key string) string { + values := s.metadata.Get(key) + if len(values) == 0 { + return "" + } + + return values[0] +} + +func (s *metadataSupplier) Set(key string, value string) { + if s.metadata != nil { + s.metadata.Set(key, value) + } +} + +func (s *metadataSupplier) Keys() []string { + out := make([]string, 0, len(*s.metadata)) + for key := range *s.metadata { + out = append(out, key) + } + + return out +} + +func extract( + ctx context.Context, + propagators propagation.TextMapPropagator, +) context.Context { + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + md = metadata.MD{} + } + + return propagators.Extract(ctx, &metadataSupplier{ + metadata: &md, + }) +} diff --git a/internal/pkg/grpc/interceptors/grpc_error/error_interceptor.go b/internal/pkg/grpc/interceptors/grpc_error/error_interceptor.go index 128c0ad2..3f267c71 100644 --- a/internal/pkg/grpc/interceptors/grpc_error/error_interceptor.go +++ b/internal/pkg/grpc/interceptors/grpc_error/error_interceptor.go @@ -2,10 +2,10 @@ package grpcError import ( "context" - "fmt" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/grpcErrors" + "emperror.dev/errors" "google.golang.org/grpc" ) @@ -18,15 +18,16 @@ func UnaryServerInterceptor() grpc.UnaryServerInterceptor { handler grpc.UnaryHandler, ) (interface{}, error) { resp, err := handler(ctx, req) - if err != nil { - grpcErr := grpcErrors.ParseError(err) - - if grpcErr != nil { - return nil, grpcErr.ToGrpcResponseErr() - } else { - prb := grpcErrors.NewInternalServerGrpcError(err.Error(), fmt.Sprintf("%+v\n", err)) - return nil, prb.ToGrpcResponseErr() - } + + var grpcErr grpcErrors.GrpcErr + + // if error was not `grpcErr` we will convert the error to a `grpcErr` + if ok := errors.As(err, &grpcErr); !ok { + grpcErr = grpcErrors.ParseError(err) + } + + if grpcErr != nil { + return nil, grpcErr.ToGrpcResponseErr() } return resp, err @@ -42,16 +43,18 @@ func StreamServerInterceptor() grpc.StreamServerInterceptor { handler grpc.StreamHandler, ) error { err := handler(srv, ss) - if err != nil { - grpcErr := grpcErrors.ParseError(err) - - if grpcErr != nil { - return grpcErr.ToGrpcResponseErr() - } else { - prb := grpcErrors.NewInternalServerGrpcError(err.Error(), fmt.Sprintf("%+v\n", err)) - return prb.ToGrpcResponseErr() - } + + var grpcErr grpcErrors.GrpcErr + + // if error was not `grpcErr` we will convert the error to a `grpcErr` + if ok := errors.As(err, &grpcErr); !ok { + grpcErr = grpcErrors.ParseError(err) + } + + if grpcErr != nil { + return grpcErr.ToGrpcResponseErr() } + return err } } diff --git a/internal/pkg/grpc/interceptors/otel_metrics/request_status_interceptor.go b/internal/pkg/grpc/interceptors/otel_metrics/request_status_interceptor.go deleted file mode 100644 index c46e1a3d..00000000 --- a/internal/pkg/grpc/interceptors/otel_metrics/request_status_interceptor.go +++ /dev/null @@ -1,84 +0,0 @@ -package otelMetrics - -// ref:https://github.com/open-telemetry/opentelemetry-go/blob/main/example/prometheus/main.go - -import ( - "context" - "fmt" - - "go.opentelemetry.io/otel/attribute" - api "go.opentelemetry.io/otel/metric" - "google.golang.org/grpc" -) - -// UnaryServerInterceptor add request status metrics to the otel -func UnaryServerInterceptor(meter api.Meter, serviceName string) grpc.UnaryServerInterceptor { - return func( - ctx context.Context, - req interface{}, - info *grpc.UnaryServerInfo, - handler grpc.UnaryHandler, - ) (interface{}, error) { - resp, err := handler(ctx, req) - - attrs := api.WithAttributes( - attribute.Key("MetricsType").String("Grpc"), - ) - - if err != nil { - counter, err := meter.Float64Counter( - fmt.Sprintf("%s_error_grpc_requests_total", serviceName), - api.WithDescription("The total number of error grpc requests"), - ) - if err != nil { - return nil, err - } - counter.Add(ctx, 1, attrs) - } else { - counter, err := meter.Float64Counter(fmt.Sprintf("%s_success_grpc_requests_total", serviceName), api.WithDescription("The total number of success grpc requests")) - if err != nil { - return nil, err - } - counter.Add(ctx, 1, attrs) - } - - return resp, err - } -} - -// StreamServerInterceptor add request status metrics to the otel -func StreamServerInterceptor(meter api.Meter, serviceName string) grpc.StreamServerInterceptor { - return func( - srv interface{}, - ss grpc.ServerStream, - info *grpc.StreamServerInfo, - handler grpc.StreamHandler, - ) error { - err := handler(srv, ss) - - attrs := api.WithAttributes( - attribute.Key("MetricsType").String("Grpc"), - ) - - ctx := ss.Context() - - if err != nil { - counter, err := meter.Float64Counter( - fmt.Sprintf("%s_error_grpc_requests_total", serviceName), - api.WithDescription("The total number of error grpc requests"), - ) - if err != nil { - return err - } - counter.Add(ctx, 1, attrs) - } else { - counter, err := meter.Float64Counter(fmt.Sprintf("%s_success_grpc_requests_total", serviceName), api.WithDescription("The total number of success grpc requests")) - if err != nil { - return err - } - counter.Add(ctx, 1, attrs) - } - - return err - } -} diff --git a/internal/pkg/grpc/server.go b/internal/pkg/grpc/server.go index 6ab48229..7285a0ea 100644 --- a/internal/pkg/grpc/server.go +++ b/internal/pkg/grpc/server.go @@ -6,8 +6,8 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/handlers" grpcError "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/interceptors/grpc_error" - otelMetrics "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/interceptors/otel_metrics" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "emperror.dev/errors" @@ -15,7 +15,6 @@ import ( grpcRecovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" grpcCtxTags "github.com/grpc-ecosystem/go-grpc-middleware/tags" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" - "go.opentelemetry.io/otel/metric" googleGrpc "google.golang.org/grpc" "google.golang.org/grpc/health" "google.golang.org/grpc/health/grpc_health_v1" @@ -48,34 +47,24 @@ type grpcServer struct { func NewGrpcServer( config *config.GrpcOptions, logger logger.Logger, - meter metric.Meter, ) GrpcServer { unaryServerInterceptors := []googleGrpc.UnaryServerInterceptor{ - // https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/example_interceptor_test.go - otelgrpc.UnaryServerInterceptor(), grpcError.UnaryServerInterceptor(), grpcCtxTags.UnaryServerInterceptor(), grpcRecovery.UnaryServerInterceptor(), } streamServerInterceptors := []googleGrpc.StreamServerInterceptor{ - // https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/example_interceptor_test.go - otelgrpc.StreamServerInterceptor(), grpcError.StreamServerInterceptor(), } - if meter != nil { - unaryServerInterceptors = append( - unaryServerInterceptors, - otelMetrics.UnaryServerInterceptor(meter, config.Name), - ) - - streamServerInterceptors = append( - streamServerInterceptors, - otelMetrics.StreamServerInterceptor(meter, config.Name), - ) - } - s := googleGrpc.NewServer( + // https://github.com/open-telemetry/opentelemetry-go-contrib/issues/2840 + // https://github.com/open-telemetry/opentelemetry-go-contrib/pull/3002 + // https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/doc.go + // https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/example/server/main.go#L143C3-L143C50 + googleGrpc.StatsHandler(otelgrpc.NewServerHandler()), + googleGrpc.StatsHandler(handlers.NewServerHandler()), + googleGrpc.KeepaliveParams(keepalive.ServerParameters{ MaxConnectionIdle: maxConnectionIdle * time.Minute, Timeout: gRPCTimeout * time.Second, diff --git a/internal/pkg/http/custom_echo/echo_server.go b/internal/pkg/http/custom_echo/echo_server.go index 995ad40a..5f34bef7 100644 --- a/internal/pkg/http/custom_echo/echo_server.go +++ b/internal/pkg/http/custom_echo/echo_server.go @@ -8,14 +8,15 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/constants" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" - customHadnlers "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/hadnlers" + hadnlers "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/hadnlers" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/middlewares/log" otelMetrics "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/middlewares/otel_metrics" + oteltracing "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/middlewares/otel_tracing" + problemdetail "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/middlewares/problem_detail" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" - "go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho" "go.opentelemetry.io/otel/metric" ) @@ -33,7 +34,7 @@ func NewEchoHttpServer( meter metric.Meter, ) contracts.EchoHttpServer { e := echo.New() - e.HideBanner = false + e.HideBanner = true return &echoHttpServer{ echo: e, @@ -97,15 +98,6 @@ func (s *echoHttpServer) GracefulShutdown(ctx context.Context) error { } func (s *echoHttpServer) SetupDefaultMiddlewares() { - // set error handler - s.echo.HTTPErrorHandler = func(err error, c echo.Context) { - // bypass notfound favicon endpoint and its error - if c.Request().URL.Path == "/favicon.ico" { - return - } - customHadnlers.ProblemHandlerFunc(err, c, s.log) - } - skipper := func(c echo.Context) bool { return strings.Contains(c.Request().URL.Path, "swagger") || strings.Contains(c.Request().URL.Path, "metrics") || @@ -113,6 +105,16 @@ func (s *echoHttpServer) SetupDefaultMiddlewares() { strings.Contains(c.Request().URL.Path, "favicon.ico") } + // set error handler + s.echo.HTTPErrorHandler = func(err error, c echo.Context) { + // bypass skip endpoints and its error + if skipper(c) { + return + } + + hadnlers.ProblemDetailErrorHandlerFunc(err, c, s.log) + } + // log errors and information s.echo.Use( log.EchoLogger( @@ -121,49 +123,21 @@ func (s *echoHttpServer) SetupDefaultMiddlewares() { ), ) s.echo.Use( - otelecho.Middleware(s.config.Name, otelecho.WithSkipper(skipper)), + oteltracing.HttpTrace(s.config.Name, oteltracing.WithSkipper(skipper)), + ) + s.echo.Use( + otelMetrics.HTTPMetrics( + otelMetrics.SetServiceName(s.config.Name), + otelMetrics.WithSkipper(skipper)), ) - // Because we use metrics server middleware, if it is not available, our echo will not work. - if s.meter != nil { - s.echo.Use(otelMetrics.Middleware(s.meter, s.config.Name)) - } - - //s.echo.Use( - // middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{ - // LogContentLength: true, - // LogLatency: true, - // LogError: false, - // LogMethod: true, - // LogRequestID: true, - // LogURI: true, - // LogResponseSize: true, - // LogURIPath: true, - // Skipper: func(c echo.Context) bool { - // return strings.Contains(c.Request().URL.Path, "swagger") || - // strings.Contains(c.Request().URL.Path, "metrics") || - // strings.Contains(c.Request().URL.Path, "health") || - // strings.Contains(c.Request().URL.Path, "favicon.ico") - // }, - // LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error { - // s.log.Infow( - // fmt.Sprintf( - // "[Request Middleware] REQUEST: uri: %v, status: %v\n", - // v.URI, - // v.Status, - // ), - // logger.Fields{"URI": v.URI, "Status": v.Status}, - // ) - // - // return nil - // }, - // }), - //) s.echo.Use(middleware.BodyLimit(constants.BodyLimit)) s.echo.Use(middleware.RequestID()) s.echo.Use(middleware.GzipWithConfig(middleware.GzipConfig{ Level: constants.GzipLevel, Skipper: skipper, })) + // should be last middleware + s.echo.Use(problemdetail.ProblemDetail(problemdetail.WithSkipper(skipper))) } func (s *echoHttpServer) ApplyVersioningFromHeader() { diff --git a/internal/pkg/http/custom_echo/hadnlers/problem_details_handler.go b/internal/pkg/http/custom_echo/hadnlers/problem_details_handler.go deleted file mode 100644 index aa5707f3..00000000 --- a/internal/pkg/http/custom_echo/hadnlers/problem_details_handler.go +++ /dev/null @@ -1,28 +0,0 @@ -package customHadnlers - -import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/problemDetails" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" - - "github.com/labstack/echo/v4" -) - -func ProblemHandlerFunc(err error, c echo.Context, logger logger.Logger) { - prb := problemDetails.ParseError(err) - - if prb != nil { - if !c.Response().Committed { - if _, err := problemDetails.WriteTo(prb, c.Response()); err != nil { - logger.Error(err) - } - } - } else { - if !c.Response().Committed { - prb := problemDetails.NewInternalServerProblemDetail(err.Error(), errorUtils.ErrorsWithStack(err)) - if _, err := problemDetails.WriteTo(prb, c.Response()); err != nil { - logger.Error(err) - } - } - } -} diff --git a/internal/pkg/http/custom_echo/hadnlers/problemdetail_error_handler.go b/internal/pkg/http/custom_echo/hadnlers/problemdetail_error_handler.go new file mode 100644 index 00000000..2cbbeab2 --- /dev/null +++ b/internal/pkg/http/custom_echo/hadnlers/problemdetail_error_handler.go @@ -0,0 +1,29 @@ +package handlers + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/problemDetails" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + + "emperror.dev/errors" + "github.com/labstack/echo/v4" +) + +func ProblemDetailErrorHandlerFunc( + err error, + c echo.Context, + logger logger.Logger, +) { + var problem problemDetails.ProblemDetailErr + + // if error was not problem detail we will convert the error to a problem detail + if ok := errors.As(err, &problem); !ok { + problem = problemDetails.ParseError(err) + } + + if !c.Response().Committed && problem != nil { + // `WriteTo` will set `Response status code` to our problem details status + if _, err := problemDetails.WriteTo(problem, c.Response()); err != nil { + logger.Error(err) + } + } +} diff --git a/internal/pkg/http/custom_echo/middlewares/log/log_middleware.go b/internal/pkg/http/custom_echo/middlewares/log/log_middleware.go index a67949e2..b179269c 100644 --- a/internal/pkg/http/custom_echo/middlewares/log/log_middleware.go +++ b/internal/pkg/http/custom_echo/middlewares/log/log_middleware.go @@ -74,7 +74,9 @@ func EchoLogger(l logger.Logger, opts ...Option) echo.MiddlewareFunc { err := requestMiddleware(next)(c) if err != nil { - // handle echo error in this middleware and raise echo errorhandler func and our custom error handler (problem details handler) + // handle echo error in this middleware and raise echo errorhandler func and our custom error handler + // when we call c.Error more than once, `c.Response().Committed` becomes true and response doesn't write to client again in our error handler + // Error will update response status with occurred error object status code c.Error(err) } diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/config.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/config.go index 698904cf..cf386453 100644 --- a/internal/pkg/http/custom_echo/middlewares/otel_metrics/config.go +++ b/internal/pkg/http/custom_echo/middlewares/otel_metrics/config.go @@ -1,9 +1,40 @@ package otelmetrics -import "github.com/labstack/echo/v4/middleware" +import ( + "github.com/labstack/echo/v4/middleware" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/metric" +) type config struct { - Skipper middleware.Skipper + metricsProvider metric.MeterProvider + + skipper middleware.Skipper + + namespace string + + serviceName string + + instrumentationName string + + // enableTotalMetric whether to enable a metric to count the total number of http requests. + enableTotalMetric bool + + // enableDurMetric whether to enable a metric to track the duration of each request. + enableDurMetric bool + + // enableDurMetric whether to enable a metric that tells the number of current in-flight requests. + enableInFlightMetric bool +} + +var defualtConfig = config{ + metricsProvider: otel.GetMeterProvider(), + enableTotalMetric: true, + enableDurMetric: true, + enableInFlightMetric: true, + skipper: middleware.DefaultSkipper, + serviceName: "application", + instrumentationName: "echo", } type Option interface { @@ -15,3 +46,65 @@ type optionFunc func(*config) func (o optionFunc) apply(c *config) { o(c) } + +// SetNamespace will set the metrics namespace that will be added to all metric configurations. It will be a prefix to each +// metric name. For example, if namespace is "myapp", then requests_total metric will be myapp_http_requests_total +// (after namespace there is also the subsystem prefix, "http" in this case). +func SetNamespace(v string) Option { + return optionFunc(func(cfg *config) { + if cfg.namespace != "" { + cfg.namespace = v + } + }) +} + +func SetServiceName(v string) Option { + return optionFunc(func(cfg *config) { + if cfg.serviceName != "" { + cfg.serviceName = v + } + }) +} + +func SetInstrumentationName(v string) Option { + return optionFunc(func(cfg *config) { + if cfg.instrumentationName != "" { + cfg.instrumentationName = v + } + }) +} + +// WithSkipper specifies a skipper for allowing requests to skip generating spans. +func WithSkipper(skipper middleware.Skipper) Option { + return optionFunc(func(cfg *config) { + cfg.skipper = skipper + }) +} + +// WithMeterProvider specifies a meter provider to use for creating a metrics. +// If none is specified, the global provider is used. +func WithMeterProvider(provider metric.MeterProvider) Option { + return optionFunc(func(cfg *config) { + if provider != nil { + cfg.metricsProvider = provider + } + }) +} + +func WithInFlightMetric(enabled bool) Option { + return optionFunc(func(cfg *config) { + cfg.enableInFlightMetric = enabled + }) +} + +func WithTotalMetric(enabled bool) Option { + return optionFunc(func(cfg *config) { + cfg.enableTotalMetric = enabled + }) +} + +func WithDurMetric(enabled bool) Option { + return optionFunc(func(cfg *config) { + cfg.enableDurMetric = enabled + }) +} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/metric.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/metric.go new file mode 100644 index 00000000..3ed99210 --- /dev/null +++ b/internal/pkg/http/custom_echo/middlewares/otel_metrics/metric.go @@ -0,0 +1,369 @@ +package otelmetrics + +// ref:https://github.com/open-telemetry/opentelemetry-go/blob/main/example/prometheus/main.go +// https://github.com/labstack/echo-contrib/blob/master/prometheus/prometheus.go +// https://github.com/worldline-go/tell/tree/main/metric/metricecho +// https://opentelemetry.io/docs/instrumentation/go/manual/#metrics +// https://opentelemetry.io/docs/specs/otel/metrics/semantic_conventions/http-metrics/ + +import ( + "context" + "fmt" + "net/http" + "time" + + "github.com/labstack/echo/v4" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" +) + +// HTTPLabels will contain HTTP label values for each added metric. Not all labels apply to all metrics, read the +// documentation in each metric method to find out which labels are available for that metric. +type HTTPLabels struct { + // Method should be the HTTP method in the HTTP request. + Method string + // Code should be the HTTP status code in the HTTP response. If there is no response, the Code should be 0. + Code int + // Path is the request URL's path. Should not contain the query string, and ideally it should only be the route + // definition. For example `/users/{ID}` instead of `/users/100`. + Path string + Host string +} + +// HTTPMetricsRecorder is a recorder of HTTP metrics for prometheus. Use NewHTTPMetricsRecorder to initialize it. +type HTTPMetricsRecorder struct { + cfg config + mp metric.MeterProvider + meter metric.Meter + reqTotal metric.Int64Counter + reqDuration metric.Float64Histogram + reqInFlight metric.Int64UpDownCounter + resSize metric.Int64Histogram + reqSize metric.Int64Histogram + errorCounter metric.Float64Counter + successCounter metric.Float64Counter +} + +// NewHTTPMetricsRecorder creates a new HTTPMetricsRecorder. Calling this function will automatically register the new metrics to reg. +func NewHTTPMetricsRecorder(cfg config) *HTTPMetricsRecorder { + // Meter can be a global/package variable. + meter := cfg.metricsProvider.Meter(cfg.instrumentationName) + + m := HTTPMetricsRecorder{ + cfg: cfg, + mp: cfg.metricsProvider, + meter: meter, + } + + if err := m.register(); err != nil { + // possible errors here include duplicate metric or same metrics with inconsistent labels or help strings. It is + // unlikely that it will happen if not by mistake. Nonetheless, we would like to know if such case occurs, hence + // a panic + panic(err) + } + + return &m +} + +func (h *HTTPMetricsRecorder) namespacedValue(v string) string { + if h.cfg.namespace != "" { + return h.cfg.namespace + "_" + v + } + + return v +} + +func (h *HTTPMetricsRecorder) register() error { + errorCounter, err := h.meter.Float64Counter( //nolint:errcheck + fmt.Sprintf("%s_error_http_requests_total", h.cfg.serviceName), + metric.WithDescription("The total number of error http requests"), + ) + if err != nil { + return fmt.Errorf( + "meter %s cannot set; %w", + fmt.Sprintf("%s_error_http_requests_total", h.cfg.serviceName), + err, + ) + } + + h.errorCounter = errorCounter + + successCounter, err := h.meter.Float64Counter( + fmt.Sprintf("%s_success_http_requests_total", h.cfg.serviceName), + metric.WithDescription("The total number of success http requests"), + ) + if err != nil { + return fmt.Errorf( + "meter %s cannot set; %w", + fmt.Sprintf("%s_success_http_requests_total", h.cfg.serviceName), + err, + ) + } + + h.successCounter = successCounter + + if h.cfg.enableTotalMetric { + reqTotal, err := h.meter.Int64Counter( + h.namespacedValue("http_requests_total"), + metric.WithDescription("The total number of requests"), + ) + if err != nil { + return fmt.Errorf( + "meter %s cannot set; %w", + "http_requests_total", + err, + ) + } + + h.reqTotal = reqTotal + } + + if h.cfg.enableDurMetric { + reqDuration, err := h.meter.Float64Histogram( + h.namespacedValue("request_duration_seconds"), + metric.WithDescription( + "The total duration of a request in seconds", + ), + ) + if err != nil { + return fmt.Errorf( + "meter %s cannot set; %w", + "request_duration_seconds", + err, + ) + } + + h.reqDuration = reqDuration + } + + if h.cfg.enableInFlightMetric { + reqInFlight, err := h.meter.Int64UpDownCounter( + h.namespacedValue("requests_inflight_total"), + metric.WithDescription("The current number of in-flight requests"), + ) + if err != nil { + return fmt.Errorf( + "meter %s cannot set; %w", + "requests_inflight_total", + err, + ) + } + + h.reqInFlight = reqInFlight + } + + resSize, err := h.meter.Int64Histogram( + h.namespacedValue("response_size"), + metric.WithDescription("The HTTP response sizes in bytes."), + ) + if err != nil { + return fmt.Errorf( + "meter %s cannot set; %w", + "response_size", + err, + ) + } + + h.resSize = resSize + + reqSize, err := h.meter.Int64Histogram( + h.namespacedValue("request_size"), + metric.WithDescription("The HTTP request sizes in bytes."), + ) + if err != nil { + return fmt.Errorf( + "meter %s cannot set; %w", + "request_size", + err, + ) + } + + h.reqSize = reqSize + + return nil +} + +// AddRequestToTotal adds 1 to the total number of requests. All labels should be specified. +func (h *HTTPMetricsRecorder) AddRequestToTotal( + ctx context.Context, + values HTTPLabels, +) { + if h.reqTotal == nil { + return + } + + h.reqTotal.Add(ctx, 1, + metric.WithAttributes( + attribute.String("method", values.Method), + attribute.Int("code", values.Code), + attribute.String("type", "Http"), + ), + ) +} + +// AddRequestDuration registers a request along with its duration. All labels should be specified. +func (h *HTTPMetricsRecorder) AddRequestDuration( + ctx context.Context, + duration time.Duration, + values HTTPLabels, +) { + if h.reqDuration == nil { + return + } + + h.reqDuration.Record( + ctx, duration.Seconds(), + metric.WithAttributes( + attribute.String("method", values.Method), + attribute.String("host", values.Host), + attribute.String("path", values.Path), + attribute.Int("code", values.Code), + attribute.String("type", "Http"), + ), + ) +} + +// AddInFlightRequest Adds 1 to the number of current in-flight requests. All labels should be specified except for +// `Code`, as it will just be ignored. To remove a request use RemInFlightRequest. +func (h *HTTPMetricsRecorder) AddInFlightRequest( + ctx context.Context, + values HTTPLabels, +) { + if h.reqInFlight == nil { + return + } + + h.reqInFlight.Add( + ctx, + 1, + metric.WithAttributes( + attribute.String("method", values.Method), + attribute.String("path", values.Path), + attribute.String("type", "Http"), + ), + ) +} + +func (h *HTTPMetricsRecorder) AddRequestError( + ctx context.Context, + values HTTPLabels, +) { + if h.errorCounter == nil { + return + } + + h.errorCounter.Add( + ctx, + 1, + metric.WithAttributes( + attribute.String("method", values.Method), + attribute.String("path", values.Path), + attribute.String("type", "Http"), + attribute.Int("code", values.Code), + ), + ) +} + +func (h *HTTPMetricsRecorder) AddRequestSuccess( + ctx context.Context, + values HTTPLabels, +) { + if h.successCounter == nil { + return + } + + h.successCounter.Add( + ctx, + 1, + metric.WithAttributes( + attribute.String("method", values.Method), + attribute.String("path", values.Path), + attribute.String("type", "Http"), + attribute.Int("code", values.Code), + ), + ) +} + +// RemInFlightRequest Remove 1 from the number of current in-flight requests. All labels should be specified except +// for `Code`, as it will just be ignored. Labels should match the ones passed to the equivalent AddInFlightRequest call. +func (h *HTTPMetricsRecorder) RemInFlightRequest( + ctx context.Context, + values HTTPLabels, +) { + if h.reqInFlight == nil { + return + } + + h.reqInFlight.Add( + ctx, + -1, + metric.WithAttributes( + attribute.String("method", values.Method), + attribute.String("path", values.Path), + attribute.String("type", "Http"), + ), + ) +} + +func (h *HTTPMetricsRecorder) AddRequestSize( + ctx context.Context, + request *http.Request, + values HTTPLabels, +) { + if h.reqSize == nil { + return + } + + size := computeApproximateRequestSize(request) + h.reqSize.Record(ctx, int64(size), metric.WithAttributes( + attribute.String("method", values.Method), + attribute.String("path", values.Path), + attribute.String("type", "Http"), + attribute.String("host", values.Host), + attribute.Int("code", values.Code), + )) +} + +func (h *HTTPMetricsRecorder) AddResponseSize( + ctx context.Context, + response *echo.Response, + values HTTPLabels, +) { + if h.resSize == nil { + return + } + + size := response.Size + h.resSize.Record(ctx, size, metric.WithAttributes( + attribute.String("method", values.Method), + attribute.String("path", values.Path), + attribute.String("type", "Http"), + attribute.String("host", values.Host), + attribute.Int("code", values.Code), + )) +} + +func computeApproximateRequestSize(r *http.Request) int { + s := 0 + if r.URL != nil { + s = len(r.URL.Path) + } + + s += len(r.Method) + s += len(r.Proto) + for name, values := range r.Header { + s += len(name) + for _, value := range values { + s += len(value) + } + } + s += len(r.Host) + + // N.B. r.Form and r.MultipartForm are assumed to be included in r.URL. + + if r.ContentLength != -1 { + s += int(r.ContentLength) + } + + return s +} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/metrics_middleware.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/metrics_middleware.go new file mode 100644 index 00000000..3312f1f5 --- /dev/null +++ b/internal/pkg/http/custom_echo/middlewares/otel_metrics/metrics_middleware.go @@ -0,0 +1,79 @@ +package otelmetrics + +// ref:https://github.com/open-telemetry/opentelemetry-go/blob/main/example/prometheus/main.go +// https://github.com/labstack/echo-contrib/blob/master/prometheus/prometheus.go +// https://github.com/worldline-go/tell/tree/main/metric/metricecho +// https://opentelemetry.io/docs/instrumentation/go/manual/#metrics + +// https://opentelemetry.io/docs/specs/otel/metrics/semantic_conventions/http-metrics/ + +import ( + "time" + + "github.com/labstack/echo/v4" +) + +// HTTPMetrics is a middleware for adding otel metrics for a given request +// If recorder config is nil, the middleware will use a recorder with default configuration. +func HTTPMetrics(opts ...Option) echo.MiddlewareFunc { + config := defualtConfig + + for _, opt := range opts { + opt.apply(&config) + } + + httpMetricsRecorder := NewHTTPMetricsRecorder(config) + + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) (err error) { + if config.skipper(c) { + return next(c) + } + + request := c.Request() + ctx := request.Context() + + values := HTTPLabels{ + Method: request.Method, + Path: c.Path(), + Host: request.URL.Host, + } + + httpMetricsRecorder.AddInFlightRequest(ctx, values) + + start := time.Now() + + defer func() { + elapsed := time.Since(start) + + values.Code = c.Response().Status + + httpMetricsRecorder.AddRequestToTotal(ctx, values) + + httpMetricsRecorder.AddRequestDuration(ctx, elapsed, values) + + httpMetricsRecorder.RemInFlightRequest(ctx, values) + + httpMetricsRecorder.AddRequestSize(ctx, request, values) + + httpMetricsRecorder.AddResponseSize(ctx, c.Response(), values) + + if err != nil { + httpMetricsRecorder.AddRequestError(ctx, values) + } else { + httpMetricsRecorder.AddRequestSuccess(ctx, values) + } + }() + + err = next(c) + if err != nil { + // handle echo error in this middleware and raise echo errorhandler func and our custom error handler + // when we call c.Error more than once, `c.Response().Committed` becomes true and response doesn't write to client again in our error handler + // Error will update response status with occurred error object status code + c.Error(err) + } + + return err + } + } +} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/request_status_middleware.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/request_status_middleware.go deleted file mode 100644 index 12e34238..00000000 --- a/internal/pkg/http/custom_echo/middlewares/otel_metrics/request_status_middleware.go +++ /dev/null @@ -1,55 +0,0 @@ -package otelmetrics - -// ref:https://github.com/open-telemetry/opentelemetry-go/blob/main/example/prometheus/main.go - -import ( - "fmt" - - "github.com/labstack/echo/v4" - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" - api "go.opentelemetry.io/otel/metric" -) - -var ( - successCounter api.Float64Counter - errorCounter api.Float64Counter -) - -// Middleware adds request status metrics to the otel -// ref: https://github.com/open-telemetry/opentelemetry-go/blob/main/example/prometheus/main.go -func Middleware(serviceName string) echo.MiddlewareFunc { - meter := otel.GetMeterProvider().Meter("echo") - - errorCounter, _ = meter.Float64Counter( //nolint:errcheck - fmt.Sprintf("%s_error_http_requests_total", serviceName), - api.WithDescription("The total number of error http requests"), - ) - successCounter, _ = meter.Float64Counter( - fmt.Sprintf("%s_success_http_requests_total", serviceName), - api.WithDescription("The total number of success http requests"), - ) - - return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - err := next(c) - request := c.Request() - ctx := request.Context() - - attrs := api.WithAttributes( - attribute.Key("MetricsType").String("Http"), - ) - - if err != nil { - errorCounter.Add(ctx, 1, attrs) - } else { - successCounter.Add(ctx, 1, attrs) - } - - // update request context - c.SetRequest(request.WithContext(ctx)) - - return err - } - } -} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/v0/prometheus.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/v0/prometheus.go deleted file mode 100644 index c8eec024..00000000 --- a/internal/pkg/http/custom_echo/middlewares/otel_metrics/v0/prometheus.go +++ /dev/null @@ -1,518 +0,0 @@ -// SPDX-License-Identifier: MIT -// SPDX-FileCopyrightText: © 2017 LabStack and Echo contributors - -/* -Package prometheus provides middleware to add Prometheus metrics. - -Example: -``` -package main -import ( - - "github.com/labstack/echo/v4" - "github.com/labstack/echo-contrib/prometheus" - -) - - func main() { - e := echo.New() - // Enable metrics middleware - p := prometheus.NewPrometheus("echo", nil) - p.Use(e) - - e.Logger.Fatal(e.Start(":1323")) - } - -``` -*/ -package prometheus - -import ( - "bytes" - "errors" - "net/http" - "os" - "strconv" - "time" - - "github.com/labstack/echo/v4" - "github.com/labstack/echo/v4/middleware" - "github.com/labstack/gommon/log" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/prometheus/common/expfmt" -) - -var ( - defaultMetricPath = "/metrics" - defaultSubsystem = "echo" -) - -const ( - _ = iota // ignore first value by assigning to blank identifier - KB float64 = 1 << (10 * iota) - MB - GB - TB -) - -// reqDurBuckets is the buckets for request duration. Here, we use the prometheus defaults -// which are for ~10s request length max: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10} -var reqDurBuckets = prometheus.DefBuckets - -// reqSzBuckets is the buckets for request size. Here we define a spectrom from 1KB thru 1NB up to 10MB. -var reqSzBuckets = []float64{ - 1.0 * KB, - 2.0 * KB, - 5.0 * KB, - 10.0 * KB, - 100 * KB, - 500 * KB, - 1.0 * MB, - 2.5 * MB, - 5.0 * MB, - 10.0 * MB, -} - -// resSzBuckets is the buckets for response size. Here we define a spectrom from 1KB thru 1NB up to 10MB. -var resSzBuckets = []float64{ - 1.0 * KB, - 2.0 * KB, - 5.0 * KB, - 10.0 * KB, - 100 * KB, - 500 * KB, - 1.0 * MB, - 2.5 * MB, - 5.0 * MB, - 10.0 * MB, -} - -// Standard default metrics -// -// counter, counter_vec, gauge, gauge_vec, -// histogram, histogram_vec, summary, summary_vec -var reqCnt = &Metric{ - ID: "reqCnt", - Name: "requests_total", - Description: "How many HTTP requests processed, partitioned by status code and HTTP method.", - Type: "counter_vec", - Args: []string{"code", "method", "host", "url"}, -} - -var reqDur = &Metric{ - ID: "reqDur", - Name: "request_duration_seconds", - Description: "The HTTP request latencies in seconds.", - Args: []string{"code", "method", "host", "url"}, - Type: "histogram_vec", - Buckets: reqDurBuckets, -} - -var resSz = &Metric{ - ID: "resSz", - Name: "response_size_bytes", - Description: "The HTTP response sizes in bytes.", - Args: []string{"code", "method", "host", "url"}, - Type: "histogram_vec", - Buckets: resSzBuckets, -} - -var reqSz = &Metric{ - ID: "reqSz", - Name: "request_size_bytes", - Description: "The HTTP request sizes in bytes.", - Args: []string{"code", "method", "host", "url"}, - Type: "histogram_vec", - Buckets: reqSzBuckets, -} - -var standardMetrics = []*Metric{ - reqCnt, - reqDur, - resSz, - reqSz, -} - -/* -RequestCounterLabelMappingFunc is a function which can be supplied to the middleware to control -the cardinality of the request counter's "url" label, which might be required in some contexts. -For instance, if for a "/customer/:name" route you don't want to generate a time series for every -possible customer name, you could use this function: - - func(c echo.Context) string { - url := c.Request.URL.Path - for _, p := range c.Params { - if p.Key == "name" { - url = strings.Replace(url, p.Value, ":name", 1) - break - } - } - return url - } - -which would map "/customer/alice" and "/customer/bob" to their template "/customer/:name". -It can also be applied for the "Host" label -*/ -type RequestCounterLabelMappingFunc func(c echo.Context) string - -// Metric is a definition for the name, description, type, ID, and -// prometheus.Collector type (i.e. CounterVec, Summary, etc) of each metric -type Metric struct { - MetricCollector prometheus.Collector - ID string - Name string - Description string - Type string - Args []string - Buckets []float64 -} - -// Prometheus contains the metrics gathered by the instance and its path -// Deprecated: use echoprometheus package instead -type Prometheus struct { - reqCnt *prometheus.CounterVec - reqDur, reqSz, resSz *prometheus.HistogramVec - router *echo.Echo - listenAddress string - Ppg PushGateway - - MetricsList []*Metric - MetricsPath string - Subsystem string - Skipper middleware.Skipper - - RequestCounterURLLabelMappingFunc RequestCounterLabelMappingFunc - RequestCounterHostLabelMappingFunc RequestCounterLabelMappingFunc - - // Context string to use as a prometheus URL label - URLLabelFromContext string -} - -// PushGateway contains the configuration for pushing to a Prometheus pushgateway (optional) -type PushGateway struct { - // Push interval in seconds - //lint:ignore ST1011 renaming would be breaking change - PushIntervalSeconds time.Duration - - // Push Gateway URL in format http://domain:port - // where JOBNAME can be any string of your choice - PushGatewayURL string - - // pushgateway job name, defaults to "echo" - Job string -} - -// NewPrometheus generates a new set of metrics with a certain subsystem name -// Deprecated: use echoprometheus package instead -func NewPrometheus(subsystem string, skipper middleware.Skipper, customMetricsList ...[]*Metric) *Prometheus { - var metricsList []*Metric - if skipper == nil { - skipper = middleware.DefaultSkipper - } - - if len(customMetricsList) > 1 { - panic("Too many args. NewPrometheus( string, ).") - } else if len(customMetricsList) == 1 { - metricsList = customMetricsList[0] - } - - metricsList = append(metricsList, standardMetrics...) - - p := &Prometheus{ - MetricsList: metricsList, - MetricsPath: defaultMetricPath, - Subsystem: defaultSubsystem, - Skipper: skipper, - RequestCounterURLLabelMappingFunc: func(c echo.Context) string { - p := c.Path() // contains route path ala `/users/:id` - if p != "" { - return p - } - // as of Echo v4.10.1 path is empty for 404 cases (when router did not find any matching routes) - // in this case we use actual path from request to have some distinction in Prometheus - return c.Request().URL.Path - }, - RequestCounterHostLabelMappingFunc: func(c echo.Context) string { - return c.Request().Host - }, - } - - p.registerMetrics(subsystem) - - return p -} - -// SetPushGateway sends metrics to a remote pushgateway exposed on pushGatewayURL -// every pushInterval. Metrics are fetched from -func (p *Prometheus) SetPushGateway(pushGatewayURL string, pushInterval time.Duration) { - p.Ppg.PushGatewayURL = pushGatewayURL - p.Ppg.PushIntervalSeconds = pushInterval - p.startPushTicker() -} - -// SetPushGatewayJob job name, defaults to "echo" -func (p *Prometheus) SetPushGatewayJob(j string) { - p.Ppg.Job = j -} - -// SetListenAddress for exposing metrics on address. If not set, it will be exposed at the -// same address of the echo engine that is being used -// func (p *Prometheus) SetListenAddress(address string) { -// p.listenAddress = address -// if p.listenAddress != "" { -// p.router = echo.Echo().Router() -// } -// } - -// SetListenAddressWithRouter for using a separate router to expose metrics. (this keeps things like GET /metrics out of -// your content's access log). -// func (p *Prometheus) SetListenAddressWithRouter(listenAddress string, r *echo.Echo) { -// p.listenAddress = listenAddress -// if len(p.listenAddress) > 0 { -// p.router = r -// } -// } - -// SetMetricsPath set metrics paths -func (p *Prometheus) SetMetricsPath(e *echo.Echo) { - if p.listenAddress != "" { - p.router.GET(p.MetricsPath, prometheusHandler()) - p.runServer() - } else { - e.GET(p.MetricsPath, prometheusHandler()) - } -} - -func (p *Prometheus) runServer() { - if p.listenAddress != "" { - go p.router.Start(p.listenAddress) - } -} - -func (p *Prometheus) getMetrics() []byte { - out := &bytes.Buffer{} - metricFamilies, _ := prometheus.DefaultGatherer.Gather() - for i := range metricFamilies { - expfmt.MetricFamilyToText(out, metricFamilies[i]) - } - return out.Bytes() -} - -func (p *Prometheus) getPushGatewayURL() string { - h, _ := os.Hostname() - if p.Ppg.Job == "" { - p.Ppg.Job = "echo" - } - return p.Ppg.PushGatewayURL + "/metrics/job/" + p.Ppg.Job + "/instance/" + h -} - -func (p *Prometheus) sendMetricsToPushGateway(metrics []byte) { - req, err := http.NewRequest("POST", p.getPushGatewayURL(), bytes.NewBuffer(metrics)) - if err != nil { - log.Errorf("failed to create push gateway request: %v", err) - return - } - client := &http.Client{} - if _, err = client.Do(req); err != nil { - log.Errorf("Error sending to push gateway: %v", err) - } -} - -func (p *Prometheus) startPushTicker() { - ticker := time.NewTicker(time.Second * p.Ppg.PushIntervalSeconds) - go func() { - for range ticker.C { - p.sendMetricsToPushGateway(p.getMetrics()) - } - }() -} - -// NewMetric associates prometheus.Collector based on Metric.Type -// Deprecated: use echoprometheus package instead -func NewMetric(m *Metric, subsystem string) prometheus.Collector { - var metric prometheus.Collector - switch m.Type { - case "counter_vec": - metric = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Subsystem: subsystem, - Name: m.Name, - Help: m.Description, - }, - m.Args, - ) - case "counter": - metric = prometheus.NewCounter( - prometheus.CounterOpts{ - Subsystem: subsystem, - Name: m.Name, - Help: m.Description, - }, - ) - case "gauge_vec": - metric = prometheus.NewGaugeVec( - prometheus.GaugeOpts{ - Subsystem: subsystem, - Name: m.Name, - Help: m.Description, - }, - m.Args, - ) - case "gauge": - metric = prometheus.NewGauge( - prometheus.GaugeOpts{ - Subsystem: subsystem, - Name: m.Name, - Help: m.Description, - }, - ) - case "histogram_vec": - metric = prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Subsystem: subsystem, - Name: m.Name, - Help: m.Description, - Buckets: m.Buckets, - }, - m.Args, - ) - case "histogram": - metric = prometheus.NewHistogram( - prometheus.HistogramOpts{ - Subsystem: subsystem, - Name: m.Name, - Help: m.Description, - Buckets: m.Buckets, - }, - ) - case "summary_vec": - metric = prometheus.NewSummaryVec( - prometheus.SummaryOpts{ - Subsystem: subsystem, - Name: m.Name, - Help: m.Description, - }, - m.Args, - ) - case "summary": - metric = prometheus.NewSummary( - prometheus.SummaryOpts{ - Subsystem: subsystem, - Name: m.Name, - Help: m.Description, - }, - ) - } - return metric -} - -func (p *Prometheus) registerMetrics(subsystem string) { - for _, metricDef := range p.MetricsList { - metric := NewMetric(metricDef, subsystem) - if err := prometheus.Register(metric); err != nil { - log.Errorf("%s could not be registered in Prometheus: %v", metricDef.Name, err) - } - switch metricDef { - case reqCnt: - p.reqCnt = metric.(*prometheus.CounterVec) - case reqDur: - p.reqDur = metric.(*prometheus.HistogramVec) - case resSz: - p.resSz = metric.(*prometheus.HistogramVec) - case reqSz: - p.reqSz = metric.(*prometheus.HistogramVec) - } - metricDef.MetricCollector = metric - } -} - -// Use adds the middleware to the Echo engine. -func (p *Prometheus) Use(e *echo.Echo) { - e.Use(p.HandlerFunc) - p.SetMetricsPath(e) -} - -// HandlerFunc defines handler function for middleware -func (p *Prometheus) HandlerFunc(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - if c.Path() == p.MetricsPath { - return next(c) - } - if p.Skipper(c) { - return next(c) - } - - start := time.Now() - reqSz := computeApproximateRequestSize(c.Request()) - - err := next(c) - - status := c.Response().Status - if err != nil { - var httpError *echo.HTTPError - if errors.As(err, &httpError) { - status = httpError.Code - } - if status == 0 || status == http.StatusOK { - status = http.StatusInternalServerError - } - } - - elapsed := float64(time.Since(start)) / float64(time.Second) - - url := p.RequestCounterURLLabelMappingFunc(c) - if len(p.URLLabelFromContext) > 0 { - u := c.Get(p.URLLabelFromContext) - if u == nil { - u = "unknown" - } - url = u.(string) - } - - statusStr := strconv.Itoa(status) - p.reqDur.WithLabelValues(statusStr, c.Request().Method, p.RequestCounterHostLabelMappingFunc(c), url). - Observe(elapsed) - p.reqCnt.WithLabelValues(statusStr, c.Request().Method, p.RequestCounterHostLabelMappingFunc(c), url).Inc() - p.reqSz.WithLabelValues(statusStr, c.Request().Method, p.RequestCounterHostLabelMappingFunc(c), url). - Observe(float64(reqSz)) - - resSz := float64(c.Response().Size) - p.resSz.WithLabelValues(statusStr, c.Request().Method, p.RequestCounterHostLabelMappingFunc(c), url). - Observe(resSz) - - return err - } -} - -func prometheusHandler() echo.HandlerFunc { - h := promhttp.Handler() - return func(c echo.Context) error { - h.ServeHTTP(c.Response(), c.Request()) - return nil - } -} - -func computeApproximateRequestSize(r *http.Request) int { - s := 0 - if r.URL != nil { - s = len(r.URL.Path) - } - - s += len(r.Method) - s += len(r.Proto) - for name, values := range r.Header { - s += len(name) - for _, value := range values { - s += len(value) - } - } - s += len(r.Host) - - // N.B. r.Form and r.MultipartForm are assumed to be included in r.URL. - - if r.ContentLength != -1 { - s += int(r.ContentLength) - } - return s -} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/metric.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/metric.go deleted file mode 100644 index 0aa8b51a..00000000 --- a/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/metric.go +++ /dev/null @@ -1,193 +0,0 @@ -package metricecho - -import ( - "context" - "fmt" - "time" - - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric" -) - -// HTTPRecorderConfig lists all available configuration options for HTTPRecorder. -type HTTPRecorderConfig struct { - // Namespace is the metrics namespace that will be added to all metric configurations. It will be a prefix to each - // metric name. For example, if Namespace is "myapp", then requests_total metric will be myapp_http_requests_total - // (after namespace there is also the subsystem prefix, "http" in this case). - Namespace string - - // EnableTotalMetric whether to enable a metric to count the total number of http requests. - EnableTotalMetric bool - - // EnableDurMetric whether to enable a metric to track the duration of each request. - EnableDurMetric bool - - // EnableDurMetric whether to enable a metric that tells the number of current in-flight requests. - EnableInFlightMetric bool -} - -// HTTPCfg has the default configuration options for HTTPRecorder. -var HTTPCfg = HTTPRecorderConfig{ - EnableTotalMetric: true, - EnableDurMetric: true, - EnableInFlightMetric: true, -} - -func (c HTTPRecorderConfig) SetNamespace(v string) HTTPRecorderConfig { - c.Namespace = v - - return c -} - -// HTTPLabels will contain HTTP label values for each added metric. Not all labels apply to all metrics, read the -// documentation in each metric method to find out which labels are available for that metric. -type HTTPLabels struct { - // Method should be the HTTP method in the HTTP request. - Method string - // Code should be the HTTP status code in the HTTP response. If there is no response, the Code should be 0. - Code int - // Path is the request URL's path. Should not contain the query string and ideally it should only be the route - // definition. For example `/users/{ID}` instead of `/users/100`. - Path string -} - -// HTTPRecorder is a recorder of HTTP metrics for prometheus. Use NewHTTPRecorder to initialize it. -type HTTPRecorder struct { - cfg HTTPRecorderConfig - mp metric.MeterProvider - reqTotal metric.Int64Counter - reqDuration metric.Float64Histogram - reqInFlight metric.Int64UpDownCounter -} - -// NewHTTPRecorder creates a new HTTPRecorder. Calling this function will automatically register the new metrics to reg. -// If meter provider is nil, it will use otel's global provider. More information about configuration options in cfg can be -// found in documentation for HTTPRecorderConfig. -func NewHTTPRecorder(cfg HTTPRecorderConfig, meterProvider metric.MeterProvider) *HTTPRecorder { - if meterProvider == nil { - meterProvider = otel.GetMeterProvider() - } - - m := HTTPRecorder{ - cfg: cfg, - mp: meterProvider, - } - - if err := m.register(); err != nil { - // possible errors here include duplicate metric or same metrics with inconsistent labels or help strings. It is - // unlikely that it will happen if not by mistake. None the less we would like to know if such case occurs, hence - // a panic - panic(err) - } - - return &m -} - -func (h *HTTPRecorder) namespacedValue(v string) string { - if h.cfg.Namespace != "" { - return h.cfg.Namespace + "_" + v - } - - return v -} - -func (h *HTTPRecorder) register() error { - meter := h.mp.Meter("") - - if h.cfg.EnableTotalMetric { - reqTotal, err := meter.Int64Counter( - h.namespacedValue("http_requests_total"), - metric.WithDescription("The total number of requests"), - ) - if err != nil { - return fmt.Errorf("meter %s cannot set; %w", "http_requests_total", err) - } - - h.reqTotal = reqTotal - } - - if h.cfg.EnableDurMetric { - reqDuration, err := meter.Float64Histogram( - h.namespacedValue("request_duration_seconds"), - metric.WithDescription("The total duration of a request in seconds"), - ) - if err != nil { - return fmt.Errorf("meter %s cannot set; %w", "request_duration_seconds", err) - } - - h.reqDuration = reqDuration - } - - if h.cfg.EnableInFlightMetric { - reqInFlight, err := meter.Int64UpDownCounter( - h.namespacedValue("requests_inflight_total"), - metric.WithDescription("The current number of in-flight requests"), - ) - if err != nil { - return fmt.Errorf("meter %s cannot set; %w", "requests_inflight_total", err) - } - - h.reqInFlight = reqInFlight - } - - return nil -} - -// AddRequestToTotal adds 1 to the total number of requests. All labels should be specified. -func (h *HTTPRecorder) AddRequestToTotal(ctx context.Context, values HTTPLabels) { - if h.reqTotal == nil { - return - } - - h.reqTotal.Add(ctx, 1, - metric.WithAttributes( - attribute.String("method", values.Method), - attribute.Int("code", values.Code), - ), - ) -} - -// AddRequestDuration registers a request along with its duration. All labels should be specified. -func (h *HTTPRecorder) AddRequestDuration(ctx context.Context, duration time.Duration, values HTTPLabels) { - if h.reqDuration == nil { - return - } - - h.reqDuration.Record( - ctx, duration.Seconds(), - metric.WithAttributes( - attribute.String("method", values.Method), - attribute.String("path", values.Path), - attribute.Int("code", values.Code), - ), - ) -} - -// AddInFlightRequest Adds 1 to the number of current in-flight requests. All labels should be specified except for -// `Code`, as it will just be ignored. To remove a request use RemInFlightRequest. -func (h *HTTPRecorder) AddInFlightRequest(ctx context.Context, values HTTPLabels) { - if h.reqInFlight == nil { - return - } - - h.reqInFlight.Add( - ctx, - 1, - metric.WithAttributes(attribute.String("method", values.Method), attribute.String("path", values.Path)), - ) -} - -// RemInFlightRequest Remove 1 from the number of current in-flight requests. All labels should be specified except -// for `Code`, as it will just be ignored. Labels should match the ones passed to the equivalent AddInFlightRequest call. -func (h *HTTPRecorder) RemInFlightRequest(ctx context.Context, values HTTPLabels) { - if h.reqInFlight == nil { - return - } - - h.reqInFlight.Add( - ctx, - -1, - metric.WithAttributes(attribute.String("method", values.Method), attribute.String("path", values.Path)), - ) -} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/middleware.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/middleware.go deleted file mode 100644 index c9a00f27..00000000 --- a/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/middleware.go +++ /dev/null @@ -1,49 +0,0 @@ -package metricecho - -import ( - "context" - "time" - - "github.com/labstack/echo/v4" -) - -// HTTPMetrics is an echo middleware to add metrics to rec for each HTTP request. -// If recorder config is nil, the middleware will use a recorder with default configuration. -func HTTPMetrics(cfg *HTTPRecorderConfig) echo.MiddlewareFunc { - if cfg == nil { - cfg = &HTTPCfg - } - - rec := NewHTTPRecorder(*cfg, nil) - - return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) (err error) { - values := HTTPLabels{ - Method: c.Request().Method, - Path: c.Path(), - } - - rec.AddInFlightRequest(context.Background(), values) - - start := time.Now() - - defer func() { - elapsed := time.Since(start) - - if err != nil { - c.Error(err) - // don't return the error so that it's not handled again - err = nil - } - - values.Code = c.Response().Status - - rec.AddRequestToTotal(context.Background(), values) - rec.AddRequestDuration(context.Background(), elapsed, values) - rec.RemInFlightRequest(context.Background(), values) - }() - - return next(c) - } - } -} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/view.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/view.go deleted file mode 100644 index 10606b17..00000000 --- a/internal/pkg/http/custom_echo/middlewares/otel_metrics/v1/view.go +++ /dev/null @@ -1,26 +0,0 @@ -package metricecho - -import ( - "github.com/worldline-go/tell/tglobal" - "go.opentelemetry.io/otel/sdk/metric" - "go.opentelemetry.io/otel/sdk/metric/aggregation" -) - -func GetViews() []metric.View { - customBucketView := metric.NewView( - metric.Instrument{ - Name: "*request_duration_seconds", - }, - metric.Stream{ - Aggregation: aggregation.ExplicitBucketHistogram{ - Boundaries: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10}, - }, - }, - ) - - return []metric.View{customBucketView} -} - -func init() { - tglobal.MetricViews.Add("echo", GetViews()) -} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/v2/otel-meter.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/v2/otel-meter.go deleted file mode 100644 index 68f13864..00000000 --- a/internal/pkg/http/custom_echo/middlewares/otel_metrics/v2/otel-meter.go +++ /dev/null @@ -1,446 +0,0 @@ -// Package otelmetric provides middleware to add opentelemetry metrics and Prometheus exporter. -package echootelmetrics - -import ( - "errors" - "net/http" - "time" - - "github.com/labstack/echo/v4" - "github.com/labstack/echo/v4/middleware" - realprometheus "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/exporters/prometheus" - "go.opentelemetry.io/otel/metric" - sdkmetric "go.opentelemetry.io/otel/sdk/metric" - "go.opentelemetry.io/otel/sdk/metric/aggregation" - "go.opentelemetry.io/otel/sdk/resource" - semconv "go.opentelemetry.io/otel/semconv/v1.20.0" -) - -// Meter can be a global/package variable. -var meter = otel.GetMeterProvider().Meter("echo") - -var ( - defaultMetricPath = "/metrics" - defaultSubsystem = "echo" -) - -const ( - _ = iota // ignore first value by assigning to blank identifier - _KB float64 = 1 << (10 * iota) - _MB - _GB - _TB -) - -const ( - unitDimensionless = "1" - unitBytes = "By" - unitMilliseconds = "ms" -) - -// reqDurBucketsMilliseconds is the buckets for request duration. Here, we use the prometheus defaults -// which are for ~10s request length max: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10} -var reqDurBucketsMilliseconds = []float64{ - .005 * 1000, - .01 * 1000, - .025 * 1000, - .05 * 1000, - .1 * 1000, - .25 * 1000, - .5 * 1000, - 1 * 1000, - 2.5 * 1000, - 5 * 1000, - 10 * 1000, -} - -var reqDurBucketsSeconds = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10} - -// byteBuckets is the buckets for request/response size. Here we define a spectrom from 1KB thru 1NB up to 10MB. -var byteBuckets = []float64{ - 1.0 * _KB, - 2.0 * _KB, - 5.0 * _KB, - 10.0 * _KB, - 100 * _KB, - 500 * _KB, - 1.0 * _MB, - 2.5 * _MB, - 5.0 * _MB, - 10.0 * _MB, -} - -/* -RequestCounterLabelMappingFunc is a function which can be supplied to the middleware to control -the cardinality of the request counter's "url" label, which might be required in some contexts. -For instance, if for a "/customer/:name" route you don't want to generate a time series for every -possible customer name, you could use this function: - - func(c echo.Context) string { - url := c.Request.URL.Path - for _, p := range c.Params { - if p.Key == "name" { - url = strings.Replace(url, p.Value, ":name", 1) - break - } - } - return url - } - -which would map "/customer/alice" and "/customer/bob" to their template "/customer/:name". -It can also be applied for the "Host" label -*/ -type RequestCounterLabelMappingFunc func(c echo.Context) string - -// MiddlewareConfig contains the configuration for creating prometheus middleware collecting several default metrics. -type MiddlewareConfig struct { - // Skipper defines a function to skip middleware. - Skipper middleware.Skipper - - // Namespace is components of the fully-qualified name of the Metric (created by joining Namespace,Subsystem and Name components with "_") - // Optional - Namespace string - - // Subsystem is components of the fully-qualified name of the Metric (created by joining Namespace,Subsystem and Name components with "_") - // Defaults to: "echo" - Subsystem string - - ServiceVersion string - - // run as [echo prometheus middleware](https://github.com/labstack/echo-contrib/blob/master/echoprometheus) compatible mode - CompatibleMode bool - - MetricsPath string - - RequestCounterURLLabelMappingFunc RequestCounterLabelMappingFunc - RequestCounterHostLabelMappingFunc RequestCounterLabelMappingFunc - - // Registry is the prometheus registry that will be used as the default Registerer and - // Gatherer if these are not specified. - Registry *realprometheus.Registry - - // Registerer sets the prometheus.Registerer instance the middleware will register these metrics with. - // Defaults to: prometheus.DefaultRegisterer - Registerer realprometheus.Registerer - - // Gatherer is the prometheus gatherer to gather metrics with. - // If not specified the Registry will be used as default. - Gatherer realprometheus.Gatherer -} - -// Prometheus contains the metrics gathered by the instance and its path -type Prometheus struct { - reqCnt metric.Int64Counter - reqDurCompatible metric.Float64Histogram - reqDur metric.Int64Histogram - reqSz, resSz metric.Int64Histogram - router *echo.Echo - - *MiddlewareConfig -} - -// NewPrometheus generates a new set of metrics with a certain subsystem name -func NewPrometheus(config MiddlewareConfig) *Prometheus { - if config.Skipper == nil { - config.Skipper = middleware.DefaultSkipper - } - - if config.Subsystem == "" { - config.Subsystem = defaultSubsystem - } - - if config.MetricsPath == "" { - config.MetricsPath = defaultMetricPath - } - - registry := realprometheus.NewRegistry() - - if config.Registry == nil { - config.Registry = registry - } - - if config.Registerer == nil { - config.Registerer = registry - } - if config.Gatherer == nil { - config.Gatherer = registry - } - - if config.RequestCounterURLLabelMappingFunc == nil { - config.RequestCounterURLLabelMappingFunc = func(c echo.Context) string { - // contains route path ala `/users/:id` - // as of Echo v4.10.1 path is empty for 404 cases (when router did not find any matching routes) - return c.Path() - } - } - - if config.RequestCounterHostLabelMappingFunc == nil { - config.RequestCounterHostLabelMappingFunc = func(c echo.Context) string { - return c.Request().Host - } - } - - p := &Prometheus{ - MiddlewareConfig: &config, - } - - var err error - // Standard default metrics - p.reqCnt, err = meter.Int64Counter( - // the result name is `requests_total` - // https://github.com/open-telemetry/opentelemetry-go/blob/46f2ce5ca6adaa264c37cdbba251c9184a06ed7f/exporters/prometheus/exporter.go#L74 - // the exporter will enforce the `_total` suffix for counter, so we do not need it here - "requests", - // see https://github.com/open-telemetry/opentelemetry-go/pull/3776 - // The go.opentelemetry.io/otel/metric/unit package is deprecated. Setup the equivalent unit string instead. (#3776) - // Setup "1" instead of unit.Dimensionless - // Setup "By" instead of unit.Bytes - // Setup "ms" instead of unit.Milliseconds - - // the exported metrics name will force suffix by unit, see - // https://github.com/open-telemetry/opentelemetry-go/blob/46f2ce5ca6adaa264c37cdbba251c9184a06ed7f/exporters/prometheus/exporter.go#L315 - // - // var unitSuffixes = map[string]string{ - // "1": "_ratio", - // "By": "_bytes", - // "ms": "_milliseconds", - // } - // disable this behaviour by using `prometheus.WithoutUnits()` option - // or hack: do not set unit for counter to avoid the `_ratio` suffix - metric.WithDescription("How many HTTP requests processed, partitioned by status code and HTTP method."), - ) - - if err != nil { - panic(err) - } - - if !p.CompatibleMode { - p.reqDur, err = meter.Int64Histogram( - "request_duration", - metric.WithUnit(unitMilliseconds), - metric.WithDescription("The HTTP request latencies in milliseconds."), - ) - if err != nil { - panic(err) - } - } else { - p.reqDurCompatible, err = meter.Float64Histogram( - "request_duration_seconds", - metric.WithUnit("s"), - metric.WithDescription("The HTTP request latencies in seconds."), - ) - if err != nil { - panic(err) - } - } - - p.resSz, err = meter.Int64Histogram( - "response_size", - metric.WithUnit(unitBytes), - metric.WithDescription("The HTTP response sizes in bytes."), - ) - if err != nil { - panic(err) - } - - p.reqSz, err = meter.Int64Histogram( - "request_size", - metric.WithUnit(unitBytes), - metric.WithDescription("The HTTP request sizes in bytes."), - ) - if err != nil { - panic(err) - } - - return p -} - -// SetMetricsExporterRoute set metrics paths -func (p *Prometheus) SetMetricsExporterRoute(e *echo.Echo) { - e.GET(p.MetricsPath, p.ExporterHandler()) -} - -// Setup adds the middleware to the Echo engine. -func (p *Prometheus) Setup(e *echo.Echo) { - e.Use(p.HandlerFunc) - p.SetMetricsExporterRoute(e) -} - -// HandlerFunc defines handler function for middleware -func (p *Prometheus) HandlerFunc(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - if c.Path() == p.MetricsPath { - return next(c) - } - if p.Skipper(c) { - return next(c) - } - - start := time.Now() - reqSz := computeApproximateRequestSize(c.Request()) - - err := next(c) - - status := c.Response().Status - if err != nil { - var httpError *echo.HTTPError - if errors.As(err, &httpError) { - status = httpError.Code - } - if status == 0 || status == http.StatusOK { - status = http.StatusInternalServerError - } - } - - elapsed := time.Since(start) / time.Millisecond - - url := p.RequestCounterURLLabelMappingFunc(c) - host := p.RequestCounterHostLabelMappingFunc(c) - - if !p.CompatibleMode { - p.reqDur.Record(c.Request().Context(), int64(elapsed), metric.WithAttributes( - attribute.Int("code", status), - attribute.String("method", c.Request().Method), - attribute.String("host", host), - attribute.String("url", url))) - } else { - elapsedSeconds := float64(elapsed) / float64(1000) - p.reqDurCompatible.Record(c.Request().Context(), elapsedSeconds, metric.WithAttributes( - attribute.Int("code", status), - attribute.String("method", c.Request().Method), - attribute.String("host", host), - attribute.String("url", url))) - } - - // "code", "method", "host", "url" - p.reqCnt.Add(c.Request().Context(), 1, - metric.WithAttributes( - attribute.Int("code", status), - attribute.String("method", c.Request().Method), - attribute.String("host", host), - attribute.String("url", url))) - - p.reqSz.Record(c.Request().Context(), int64(reqSz), - metric.WithAttributes( - attribute.Int("code", status), - attribute.String("method", c.Request().Method), - attribute.String("host", host), - attribute.String("url", url))) - - resSz := float64(c.Response().Size) - p.resSz.Record(c.Request().Context(), int64(resSz), - metric.WithAttributes( - attribute.Int("code", status), - attribute.String("method", c.Request().Method), - attribute.String("host", host), - attribute.String("url", url))) - - return err - } -} - -func (p *Prometheus) initMetricsExporter() *prometheus.Exporter { - serviceName := p.Subsystem - res, err := resource.Merge(resource.Default(), - resource.NewSchemaless( - semconv.ServiceName(serviceName), - semconv.ServiceVersion(p.ServiceVersion), - )) - if err != nil { - panic(err) - } - - opts := []prometheus.Option{ - prometheus.WithRegisterer(p.Registerer), - prometheus.WithNamespace(serviceName), - } - if p.CompatibleMode { - opts = append(opts, prometheus.WithoutScopeInfo()) - } - exporter, err := prometheus.New(opts...) - if err != nil { - panic(err) - } - - durationBucketsView := sdkmetric.NewView( - sdkmetric.Instrument{Name: "*_duration_milliseconds"}, - sdkmetric.Stream{Aggregation: aggregation.ExplicitBucketHistogram{ - Boundaries: reqDurBucketsMilliseconds, - }}, - ) - if p.CompatibleMode { - durationBucketsView = sdkmetric.NewView( - sdkmetric.Instrument{Name: "*_duration_seconds"}, - sdkmetric.Stream{Aggregation: aggregation.ExplicitBucketHistogram{ - Boundaries: reqDurBucketsSeconds, - }}, - ) - } - - reqBytesBucketsView := sdkmetric.NewView( - sdkmetric.Instrument{Name: "*request_size"}, - sdkmetric.Stream{Aggregation: aggregation.ExplicitBucketHistogram{ - Boundaries: byteBuckets, - }}, - ) - - rspBytesBucketsView := sdkmetric.NewView( - sdkmetric.Instrument{Name: "*response_size"}, - sdkmetric.Stream{Aggregation: aggregation.ExplicitBucketHistogram{ - Boundaries: byteBuckets, - }}, - ) - - defaultView := sdkmetric.NewView(sdkmetric.Instrument{Name: "*", Kind: sdkmetric.InstrumentKindCounter}, - sdkmetric.Stream{}) - - provider := sdkmetric.NewMeterProvider( - sdkmetric.WithResource(res), - // view see https://github.com/open-telemetry/opentelemetry-go/blob/v1.11.2/exporters/prometheus/exporter_test.go#L291 - sdkmetric.WithReader(exporter), - sdkmetric.WithView(durationBucketsView, reqBytesBucketsView, rspBytesBucketsView, defaultView), - ) - - otel.SetMeterProvider(provider) - - return exporter -} - -func (p *Prometheus) ExporterHandler() echo.HandlerFunc { - p.initMetricsExporter() - - h := promhttp.HandlerFor(p.Gatherer, promhttp.HandlerOpts{}) - - return func(c echo.Context) error { - h.ServeHTTP(c.Response(), c.Request()) - return nil - } -} - -func computeApproximateRequestSize(r *http.Request) int { - s := 0 - if r.URL != nil { - s = len(r.URL.Path) - } - - s += len(r.Method) - s += len(r.Proto) - for name, values := range r.Header { - s += len(name) - for _, value := range values { - s += len(value) - } - } - s += len(r.Host) - - // N.B. r.Form and r.MultipartForm are assumed to be included in r.URL. - - if r.ContentLength != -1 { - s += int(r.ContentLength) - } - return s -} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/view.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/view.go new file mode 100644 index 00000000..c2dc5532 --- /dev/null +++ b/internal/pkg/http/custom_echo/middlewares/otel_metrics/view.go @@ -0,0 +1,33 @@ +package otelmetrics + +import ( + "go.opentelemetry.io/otel/sdk/metric" +) + +// https://opentelemetry.io/docs/instrumentation/go/manual/#registering-views +func GetViews() []metric.View { + customBucketView := metric.NewView( + metric.Instrument{ + Name: "*request_duration_seconds", + }, + metric.Stream{ + Aggregation: metric.AggregationExplicitBucketHistogram{ + Boundaries: []float64{ + .005, + .01, + .025, + .05, + .1, + .25, + .5, + 1, + 2.5, + 5, + 10, + }, + }, + }, + ) + + return []metric.View{customBucketView} +} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_tracing/config.go b/internal/pkg/http/custom_echo/middlewares/otel_tracing/config.go new file mode 100644 index 00000000..2f265374 --- /dev/null +++ b/internal/pkg/http/custom_echo/middlewares/otel_tracing/config.go @@ -0,0 +1,72 @@ +package oteltracing + +import ( + "github.com/labstack/echo/v4/middleware" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/propagation" + oteltrace "go.opentelemetry.io/otel/trace" +) + +// Ref: https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/github.com/labstack/echo/otelecho/echo.go + +// config is used to configure the mux middleware. +type config struct { + tracerProvider oteltrace.TracerProvider + propagators propagation.TextMapPropagator + skipper middleware.Skipper + instrumentationName string +} + +// Option specifies instrumentation configuration options. +type Option interface { + apply(*config) +} + +type optionFunc func(*config) + +func (o optionFunc) apply(c *config) { + o(c) +} + +var defualtConfig = config{ + tracerProvider: otel.GetTracerProvider(), + propagators: otel.GetTextMapPropagator(), + skipper: middleware.DefaultSkipper, + instrumentationName: "echo", +} + +// WithPropagators specifies propagators to use for extracting +// information from the HTTP requests. If none are specified, global +// ones will be used. +func WithPropagators(propagators propagation.TextMapPropagator) Option { + return optionFunc(func(cfg *config) { + if propagators != nil { + cfg.propagators = propagators + } + }) +} + +// WithTracerProvider specifies a tracer provider to use for creating a tracer. +// If none is specified, the global provider is used. +func WithTracerProvider(provider oteltrace.TracerProvider) Option { + return optionFunc(func(cfg *config) { + if provider != nil { + cfg.tracerProvider = provider + } + }) +} + +// WithSkipper specifies a skipper for allowing requests to skip generating spans. +func WithSkipper(skipper middleware.Skipper) Option { + return optionFunc(func(cfg *config) { + cfg.skipper = skipper + }) +} + +func SetInstrumentationName(v string) Option { + return optionFunc(func(cfg *config) { + if cfg.instrumentationName != "" { + cfg.instrumentationName = v + } + }) +} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_tracing/tracing_middleware.go b/internal/pkg/http/custom_echo/middlewares/otel_tracing/tracing_middleware.go new file mode 100644 index 00000000..877e26ce --- /dev/null +++ b/internal/pkg/http/custom_echo/middlewares/otel_tracing/tracing_middleware.go @@ -0,0 +1,96 @@ +package oteltracing + +// Ref: https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/github.com/labstack/echo/otelecho/echo.go +// Note: for consideration of 4xx status as error in traces, I customized original echo oteltrace middleware for handing my requirements + +// https://opentelemetry.io/docs/specs/otel/trace/semantic_conventions/http/ + +import ( + "fmt" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/utils" + + "github.com/labstack/echo/v4" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/semconv/v1.20.0/httpconv" + semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + oteltrace "go.opentelemetry.io/otel/trace" +) + +// HttpTrace returns echo middleware which will trace incoming requests. +func HttpTrace(service string, opts ...Option) echo.MiddlewareFunc { + cfg := defualtConfig + for _, opt := range opts { + opt.apply(&cfg) + } + + tracer := cfg.tracerProvider.Tracer(cfg.instrumentationName) + + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + if cfg.skipper(c) { + return next(c) + } + + c.Set(cfg.instrumentationName, tracer) + request := c.Request() + // doesn't contain trace information and after completing trace on new ctx we should go back to our old savedCtx + savedCtx := request.Context() + + defer func() { + // we should go back to previous context in end of our operation because new context contains child spans, and if we don't set it back to previous context, after returning from this method all further parent spans becomes a new child for existing child span! + request = request.WithContext(savedCtx) + c.SetRequest(request) + }() + + // create new ctx from existing savedCtx + ctx := cfg.propagators.Extract( + savedCtx, + propagation.HeaderCarrier(request.Header), + ) + + // //https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md + // httpconv doesn't exist in semconv v1.21.0 we have to use v1.20.0 for that + // https://github.com/open-telemetry/opentelemetry-go/pull/4362 + opts := []oteltrace.SpanStartOption{ + oteltrace.WithAttributes( + httpconv.ServerRequest(service, request)...), + oteltrace.WithSpanKind(oteltrace.SpanKindServer), + } + + if path := c.Path(); path != "" { + rAttr := semconv.HTTPRoute(path) + opts = append(opts, oteltrace.WithAttributes(rAttr)) + } + + spanName := c.Path() + if spanName == "" { + spanName = fmt.Sprintf( + "HTTP %s route not found", + request.Method, + ) + } + + ctx, span := tracer.Start(ctx, spanName, opts...) + defer span.End() + + // add the new context into the request, because new ctx contains our created span and we want all inner spans in next middlewares become child span of this span + // pass the span through the request context + c.SetRequest(request.WithContext(ctx)) + + // serve the request to the next middleware + err := next(c) + if err != nil { + // handle echo error in this middleware and raise echo errorhandler func and our custom error handler + // when we call c.Error more than once, `c.Response().Committed` becomes true and response doesn't write to client again in our error handler + // Error will update response status with occurred error object status code + c.Error(err) + } + + status := c.Response().Status + err = utils.HttpTraceFromSpanWithCode(span, err, status) + + return err + } + } +} diff --git a/internal/pkg/http/custom_echo/middlewares/problem_detail/config.go b/internal/pkg/http/custom_echo/middlewares/problem_detail/config.go new file mode 100644 index 00000000..715133a7 --- /dev/null +++ b/internal/pkg/http/custom_echo/middlewares/problem_detail/config.go @@ -0,0 +1,34 @@ +package problemdetail + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/problemDetails" + + "github.com/labstack/echo/v4/middleware" +) + +type config struct { + Skipper middleware.Skipper + ProblemParser problemDetails.ErrorParserFunc +} + +type Option interface { + apply(*config) +} + +type optionFunc func(*config) + +func (o optionFunc) apply(c *config) { + o(c) +} + +func WithSkipper(skipper middleware.Skipper) Option { + return optionFunc(func(cfg *config) { + cfg.Skipper = skipper + }) +} + +func WithErrorParser(errorParser problemDetails.ErrorParserFunc) Option { + return optionFunc(func(cfg *config) { + cfg.ProblemParser = errorParser + }) +} diff --git a/internal/pkg/http/custom_echo/middlewares/problem_detail/problem_detail_middleware.go b/internal/pkg/http/custom_echo/middlewares/problem_detail/problem_detail_middleware.go new file mode 100644 index 00000000..829548d9 --- /dev/null +++ b/internal/pkg/http/custom_echo/middlewares/problem_detail/problem_detail_middleware.go @@ -0,0 +1,44 @@ +package problemdetail + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/problemDetails" + + "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" +) + +func ProblemDetail(opts ...Option) echo.MiddlewareFunc { + cfg := config{} + for _, opt := range opts { + opt.apply(&cfg) + } + + if cfg.Skipper == nil { + cfg.Skipper = middleware.DefaultSkipper + } + + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + if cfg.Skipper(c) { + return next(c) + } + + err := next(c) + + prbError := problemDetails.ParseError(err) + + if cfg.ProblemParser != nil { + prbError = cfg.ProblemParser(prbError) + } + + if prbError != nil { + // handle echo error in this middleware and raise echo errorhandler func and our custom error handler + // when we call c.Error more than once, `c.Response().Committed` becomes true and response doesn't write to client again in our error handler + // Error will update response status with occurred error object status code + c.Error(prbError) + } + + return prbError + } + } +} diff --git a/internal/pkg/http/custom_echo/utils/tracing.go b/internal/pkg/http/custom_echo/utils/tracing.go index bea19d42..342c357e 100644 --- a/internal/pkg/http/custom_echo/utils/tracing.go +++ b/internal/pkg/http/custom_echo/utils/tracing.go @@ -2,6 +2,7 @@ package utils import ( "context" + "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/constants" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" @@ -10,56 +11,89 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/semconv/v1.20.0/httpconv" semconv "go.opentelemetry.io/otel/semconv/v1.21.0" "go.opentelemetry.io/otel/trace" ) -// TraceHttpErrFromSpan setting span with status error with error message -func TraceHttpErrFromSpan(span trace.Span, err error) error { - if err != nil { +// HttpTraceFromSpan create an error span if we have an error and a successful span when error is nil +func HttpTraceFromSpan(span trace.Span, err error) error { + isError := err != nil + + if customErrors.IsCustomError(err) { + httpError := problemDetails.ParseError(err) + + return HttpTraceFromSpanWithCode( + span, + err, + httpError.GetStatus(), + ) + } + + var ( + status int + code codes.Code + ) + + if isError { + status = http.StatusInternalServerError + code = codes.Error + } else { + status = http.StatusOK + code = codes.Ok + } + + span.SetStatus(code, "") + span.SetAttributes( + semconv.HTTPStatusCode(status), + ) + + if isError { stackTraceError := errorUtils.ErrorsWithStack(err) - span.SetStatus(codes.Error, "") + + // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors span.SetAttributes( attribute.String(constants.Otel.HttpErrorMessage, stackTraceError), ) - if customErrors.IsCustomError(err) { - httpError := problemDetails.ParseError(err) - span.SetAttributes(semconv.HTTPStatusCode(httpError.GetStatus())) - } span.RecordError(err) } return err } -// TraceHttpErrFromSpanWithCode setting span with status error with error message -func TraceHttpErrFromSpanWithCode(span trace.Span, err error, code int) error { +// HttpTraceFromSpanWithCode create an error span with specific status code if we have an error and a successful span when error is nil with a specific status +func HttpTraceFromSpanWithCode(span trace.Span, err error, code int) error { if err != nil { stackTraceError := errorUtils.ErrorsWithStack(err) - span.SetStatus(codes.Error, "") - span.SetAttributes(semconv.HTTPStatusCode(code)) + + // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors span.SetAttributes( attribute.String(constants.Otel.HttpErrorMessage, stackTraceError), ) span.RecordError(err) } + if code > 0 { + // httpconv doesn't exist in semconv v1.21.0, and it moved to `opentelemetry-go-contrib` pkg + // https://github.com/open-telemetry/opentelemetry-go/pull/4362 + // https://github.com/open-telemetry/opentelemetry-go/issues/4081 + // using ClientStatus instead of ServerStatus for consideration of 4xx status as error + span.SetStatus(httpconv.ClientStatus(code)) + span.SetAttributes(semconv.HTTPStatusCode(code)) + } else { + span.SetStatus(codes.Error, "") + span.SetAttributes(semconv.HTTPStatusCode(http.StatusInternalServerError)) + } + return err } -func TraceHttpErrFromContext(ctx context.Context, err error) error { +// HttpTraceFromContext create an error span if we have an error and a successful span when error is nil +func HttpTraceFromContext(ctx context.Context, err error) error { // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors span := trace.SpanFromContext(ctx) - defer span.End() - if err != nil { - stackTraceError := errorUtils.ErrorsWithStack(err) - span.SetStatus(codes.Error, "") - span.SetAttributes( - attribute.String(constants.Otel.HttpErrorMessage, stackTraceError), - ) - span.RecordError(err) - } + defer span.End() - return err + return HttpTraceFromSpan(span, err) } diff --git a/internal/pkg/http/http_errors/custom_errors/api_error.go b/internal/pkg/http/http_errors/custom_errors/api_error.go index 21232e7b..b451f925 100644 --- a/internal/pkg/http/http_errors/custom_errors/api_error.go +++ b/internal/pkg/http/http_errors/custom_errors/api_error.go @@ -28,18 +28,18 @@ type apiError struct { type ApiError interface { CustomError - IsApiError() bool } -func (a *apiError) IsApiError() bool { +func (a *apiError) isAPIError() bool { return true } func IsApiError(err error, code int) bool { - var apiError ApiError + var apiError *apiError + // us, ok := grpc_errors.Cause(err).(ApiError) if errors.As(err, &apiError) { - return apiError.IsApiError() && apiError.Status() == code + return apiError.isAPIError() && apiError.Status() == code } return false diff --git a/internal/pkg/http/http_errors/custom_errors/application_error.go b/internal/pkg/http/http_errors/custom_errors/application_error.go index 3d083526..91a6f5b2 100644 --- a/internal/pkg/http/http_errors/custom_errors/application_error.go +++ b/internal/pkg/http/http_errors/custom_errors/application_error.go @@ -8,7 +8,11 @@ import ( func NewApplicationError(message string) error { ae := &applicationError{ - CustomError: NewCustomError(nil, http.StatusInternalServerError, message), + CustomError: NewCustomError( + nil, + http.StatusInternalServerError, + message, + ), } stackErr := errors.WithStackIf(ae) @@ -26,14 +30,22 @@ func NewApplicationErrorWithCode(message string, code int) error { func NewApplicationErrorWrap(err error, message string) error { ae := &applicationError{ - CustomError: NewCustomError(err, http.StatusInternalServerError, message), + CustomError: NewCustomError( + err, + http.StatusInternalServerError, + message, + ), } stackErr := errors.WithStackIf(ae) return stackErr } -func NewApplicationErrorWrapWithCode(err error, code int, message string) error { +func NewApplicationErrorWrapWithCode( + err error, + code int, + message string, +) error { ae := &applicationError{ CustomError: NewCustomError(err, code, message), } @@ -48,18 +60,18 @@ type applicationError struct { type ApplicationError interface { CustomError - IsApplicationError() bool } -func (a *applicationError) IsApplicationError() bool { +func (a *applicationError) isApplicationError() bool { return true } func IsApplicationError(err error, code int) bool { - var applicationError ApplicationError + var applicationError *applicationError // us, ok := grpc_errors.Cause(err).(ApplicationError) if errors.As(err, &applicationError) { - return applicationError.IsApplicationError() && applicationError.Status() == code + return applicationError.isApplicationError() && + applicationError.Status() == code } return false diff --git a/internal/pkg/http/http_errors/custom_errors/bad_request_error.go b/internal/pkg/http/http_errors/custom_errors/bad_request_error.go index 20104d44..c98a0640 100644 --- a/internal/pkg/http/http_errors/custom_errors/bad_request_error.go +++ b/internal/pkg/http/http_errors/custom_errors/bad_request_error.go @@ -30,18 +30,17 @@ type badRequestError struct { type BadRequestError interface { CustomError - IsBadRequestError() bool } -func (b *badRequestError) IsBadRequestError() bool { +func (b *badRequestError) isBadRequestError() bool { return true } func IsBadRequestError(err error) bool { - var badRequestError BadRequestError + var badRequestError *badRequestError // us, ok := grpc_errors.Cause(err).(BadRequestError) if errors.As(err, &badRequestError) { - return badRequestError.IsBadRequestError() + return badRequestError.isBadRequestError() } return false diff --git a/internal/pkg/http/http_errors/custom_errors/conflict_error.go b/internal/pkg/http/http_errors/custom_errors/conflict_error.go index a7194368..7361aa29 100644 --- a/internal/pkg/http/http_errors/custom_errors/conflict_error.go +++ b/internal/pkg/http/http_errors/custom_errors/conflict_error.go @@ -30,18 +30,17 @@ type conflictError struct { type ConflictError interface { CustomError - IsConflictError() bool } -func (c *conflictError) IsConflictError() bool { +func (c *conflictError) isConflictError() bool { return true } func IsConflictError(err error) bool { - var conflictError ConflictError + var conflictError *conflictError // us, ok := grpc_errors.Cause(err).(ConflictError) if errors.As(err, &conflictError) { - return conflictError.IsConflictError() + return conflictError.isConflictError() } return false diff --git a/internal/pkg/http/http_errors/custom_errors/domain_error.go b/internal/pkg/http/http_errors/custom_errors/domain_error.go index 38720d6b..6a46dd4d 100644 --- a/internal/pkg/http/http_errors/custom_errors/domain_error.go +++ b/internal/pkg/http/http_errors/custom_errors/domain_error.go @@ -48,18 +48,17 @@ type domainError struct { type DomainError interface { CustomError - IsDomainError() bool } -func (d *domainError) IsDomainError() bool { +func (d *domainError) isDomainError() bool { return true } func IsDomainError(err error, code int) bool { - var domainErr DomainError + var domainErr *domainError // us, ok := grpc_errors.Cause(err).(DomainError) if errors.As(err, &domainErr) { - return domainErr.IsDomainError() && domainErr.Status() == code + return domainErr.isDomainError() && domainErr.Status() == code } return false diff --git a/internal/pkg/http/http_errors/custom_errors/forbiden_error.go b/internal/pkg/http/http_errors/custom_errors/forbiden_error.go index 0a35add3..ac285abf 100644 --- a/internal/pkg/http/http_errors/custom_errors/forbiden_error.go +++ b/internal/pkg/http/http_errors/custom_errors/forbiden_error.go @@ -30,18 +30,17 @@ type forbiddenError struct { type ForbiddenError interface { CustomError - IsForbiddenError() bool } -func (f *forbiddenError) IsForbiddenError() bool { +func (f *forbiddenError) isForbiddenError() bool { return true } func IsForbiddenError(err error) bool { - var forbiddenError ForbiddenError + var forbiddenError *forbiddenError // us, ok := grpc_errors.Cause(err).(ForbiddenError) if errors.As(err, &forbiddenError) { - return forbiddenError.IsForbiddenError() + return forbiddenError.isForbiddenError() } return false diff --git a/internal/pkg/http/http_errors/custom_errors/internal_server_error.go b/internal/pkg/http/http_errors/custom_errors/internal_server_error.go index f6db30a5..391d6156 100644 --- a/internal/pkg/http/http_errors/custom_errors/internal_server_error.go +++ b/internal/pkg/http/http_errors/custom_errors/internal_server_error.go @@ -30,18 +30,17 @@ type internalServerError struct { type InternalServerError interface { CustomError - IsInternalServerError() bool } -func (i *internalServerError) IsInternalServerError() bool { +func (i *internalServerError) isInternalServerError() bool { return true } func IsInternalServerError(err error) bool { - var internalErr InternalServerError + var internalErr *internalServerError // us, ok := grpc_errors.Cause(err).(InternalServerError) if errors.As(err, &internalErr) { - return internalErr.IsInternalServerError() + return internalErr.isInternalServerError() } return false diff --git a/internal/pkg/http/http_errors/custom_errors/marshaling_error.go b/internal/pkg/http/http_errors/custom_errors/marshaling_error.go index 84ce3853..0520588a 100644 --- a/internal/pkg/http/http_errors/custom_errors/marshaling_error.go +++ b/internal/pkg/http/http_errors/custom_errors/marshaling_error.go @@ -32,19 +32,18 @@ type marshalingError struct { type MarshalingError interface { InternalServerError - IsMarshalingError() bool } -func (m *marshalingError) IsMarshalingError() bool { +func (m *marshalingError) isMarshalingError() bool { return true } func IsMarshalingError(err error) bool { - var me MarshalingError + var me *marshalingError // us, ok := grpc_errors.Cause(err).(MarshalingError) if errors.As(err, &me) { - return me.IsMarshalingError() + return me.isMarshalingError() } return false diff --git a/internal/pkg/http/http_errors/custom_errors/not_found_error.go b/internal/pkg/http/http_errors/custom_errors/not_found_error.go index a334c7c7..24f2c7c0 100644 --- a/internal/pkg/http/http_errors/custom_errors/not_found_error.go +++ b/internal/pkg/http/http_errors/custom_errors/not_found_error.go @@ -30,18 +30,17 @@ type notFoundError struct { type NotFoundError interface { CustomError - IsNotFoundError() bool } -func (n *notFoundError) IsNotFoundError() bool { +func (n *notFoundError) isNotFoundError() bool { return true } func IsNotFoundError(err error) bool { - var notFoundError NotFoundError + var notFoundError *notFoundError // us, ok := grpc_errors.Cause(err).(NotFoundError) if errors.As(err, ¬FoundError) { - return notFoundError.IsNotFoundError() + return notFoundError.isNotFoundError() } return false diff --git a/internal/pkg/http/http_errors/custom_errors/unauthorized_error.go b/internal/pkg/http/http_errors/custom_errors/unauthorized_error.go index 51638b5a..d7e66d16 100644 --- a/internal/pkg/http/http_errors/custom_errors/unauthorized_error.go +++ b/internal/pkg/http/http_errors/custom_errors/unauthorized_error.go @@ -30,18 +30,17 @@ type unauthorizedError struct { type UnauthorizedError interface { CustomError - IsUnAuthorizedError() bool } -func (u *unauthorizedError) IsUnAuthorizedError() bool { +func (u *unauthorizedError) isUnAuthorizedError() bool { return true } func IsUnAuthorizedError(err error) bool { - var unauthorizedError UnauthorizedError + var unauthorizedError *unauthorizedError // us, ok := grpc_errors.Cause(err).(UnauthorizedError) if errors.As(err, &unauthorizedError) { - return unauthorizedError.IsUnAuthorizedError() + return unauthorizedError.isUnAuthorizedError() } return false diff --git a/internal/pkg/http/http_errors/custom_errors/unmarshaling_error.go b/internal/pkg/http/http_errors/custom_errors/unmarshaling_error.go index b65dec8d..58c5b713 100644 --- a/internal/pkg/http/http_errors/custom_errors/unmarshaling_error.go +++ b/internal/pkg/http/http_errors/custom_errors/unmarshaling_error.go @@ -32,18 +32,17 @@ type unMarshalingError struct { type UnMarshalingError interface { InternalServerError - IsUnMarshalingError() bool } -func (u *unMarshalingError) IsUnMarshalingError() bool { +func (u *unMarshalingError) isUnMarshalingError() bool { return true } func IsUnMarshalingError(err error) bool { - var unMarshalingError UnMarshalingError + var unMarshalingError *unMarshalingError // us, ok := grpc_errors.Cause(err).(UnMarshalingError) if errors.As(err, &unMarshalingError) { - return unMarshalingError.IsUnMarshalingError() + return unMarshalingError.isUnMarshalingError() } return false diff --git a/internal/pkg/http/http_errors/custom_errors/validation_error.go b/internal/pkg/http/http_errors/custom_errors/validation_error.go index b2d2dda8..938501fb 100644 --- a/internal/pkg/http/http_errors/custom_errors/validation_error.go +++ b/internal/pkg/http/http_errors/custom_errors/validation_error.go @@ -32,18 +32,17 @@ type validationError struct { type ValidationError interface { BadRequestError - IsValidationError() bool } -func (v *validationError) IsValidationError() bool { +func (v *validationError) isValidationError() bool { return true } func IsValidationError(err error) bool { - var validationError ValidationError + var validationError *validationError // us, ok := grpc_errors.Cause(err).(ValidationError) if errors.As(err, &validationError) { - return validationError.IsValidationError() + return validationError.isValidationError() } return false diff --git a/internal/pkg/http/http_errors/problemDetails/problem_detail_parser.go b/internal/pkg/http/http_errors/problemDetails/problem_detail_parser.go index 85bfd2ae..bc5deaf0 100644 --- a/internal/pkg/http/http_errors/problemDetails/problem_detail_parser.go +++ b/internal/pkg/http/http_errors/problemDetails/problem_detail_parser.go @@ -19,7 +19,11 @@ type ProblemDetailParser struct { internalErrors map[reflect.Type]func(err error) ProblemDetailErr } -func NewProblemDetailParser(builder func(builder *OptionBuilder)) *ProblemDetailParser { +type ErrorParserFunc func(err error) ProblemDetailErr + +func NewProblemDetailParser( + builder func(builder *OptionBuilder), +) *ProblemDetailParser { optionBuilder := NewOptionBuilder() builder(optionBuilder) items := optionBuilder.Build() @@ -40,14 +44,26 @@ func ParseError(err error) ProblemDetailErr { customErr := customErrors.GetCustomError(err) var validatorErr validator.ValidationErrors - if err != nil { + if err != nil && customErr != nil { switch { case customErrors.IsDomainError(err, customErr.Status()): - return NewDomainProblemDetail(customErr.Status(), customErr.Error(), stackTrace) + return NewDomainProblemDetail( + customErr.Status(), + customErr.Error(), + stackTrace, + ) case customErrors.IsApplicationError(err, customErr.Status()): - return NewApplicationProblemDetail(customErr.Status(), customErr.Error(), stackTrace) + return NewApplicationProblemDetail( + customErr.Status(), + customErr.Error(), + stackTrace, + ) case customErrors.IsApiError(err, customErr.Status()): - return NewApiProblemDetail(customErr.Status(), customErr.Error(), stackTrace) + return NewApiProblemDetail( + customErr.Status(), + customErr.Error(), + stackTrace, + ) case customErrors.IsBadRequestError(err): return NewBadRequestProblemDetail(customErr.Error(), stackTrace) case customErrors.IsNotFoundError(err): @@ -55,7 +71,10 @@ func ParseError(err error) ProblemDetailErr { case customErrors.IsValidationError(err): return NewValidationProblemDetail(customErr.Error(), stackTrace) case customErrors.IsUnAuthorizedError(err): - return NewUnAuthorizedErrorProblemDetail(customErr.Error(), stackTrace) + return NewUnAuthorizedErrorProblemDetail( + customErr.Error(), + stackTrace, + ) case customErrors.IsForbiddenError(err): return NewForbiddenProblemDetail(customErr.Error(), stackTrace) case customErrors.IsConflictError(err): @@ -63,11 +82,21 @@ func ParseError(err error) ProblemDetailErr { case customErrors.IsInternalServerError(err): return NewInternalServerProblemDetail(customErr.Error(), stackTrace) case customErrors.IsCustomError(err): - return NewProblemDetailFromCodeAndDetail(customErr.Status(), customErr.Error(), stackTrace) + return NewProblemDetailFromCodeAndDetail( + customErr.Status(), + customErr.Error(), + stackTrace, + ) case customErrors.IsUnMarshalingError(err): return NewInternalServerProblemDetail(err.Error(), stackTrace) case customErrors.IsMarshalingError(err): return NewInternalServerProblemDetail(err.Error(), stackTrace) + + default: + return NewInternalServerProblemDetail(err.Error(), stackTrace) + } + } else if err != nil && customErr == nil { + switch { case errors.Is(err, sql.ErrNoRows): return NewNotFoundErrorProblemDetail(err.Error(), stackTrace) case errors.Is(err, context.DeadlineExceeded): diff --git a/internal/pkg/otel/metrics/metrics.go b/internal/pkg/otel/metrics/metrics.go index c4300b35..1f42595d 100644 --- a/internal/pkg/otel/metrics/metrics.go +++ b/internal/pkg/otel/metrics/metrics.go @@ -2,6 +2,7 @@ package metrics // https://github.com/riferrei/otel-with-golang/blob/main/main.go // https://github.com/open-telemetry/opentelemetry-go/blob/main/example/prometheus/main.go +// https://opentelemetry.io/docs/instrumentation/go/manual/#metrics import ( "context" @@ -216,20 +217,49 @@ func (o *OtelMetrics) configExporters() ([]metric.Reader, error) { exporters = append(exporters, uptraceExporter) } - - // https://prometheus.io/docs/prometheus/latest/getting_started/ - // https://prometheus.io/docs/guides/go-application/ - // prometheus exporter will collect otel metrics in prometheus registry - // all prometheus exporters will add to a singleton `prometheus.DefaultRegisterer` registry in newConfig method and this registry will use via `promhttp.Handler` through http endpoint on `/metrics` and calls `Collect` on prometheus Reader interface inner signature prometheus.DefaultRegisterer - prometheusExporter, err := prometheus.New() - if err != nil { - return nil, errors.WrapIf( - err, - "error creating prometheus exporter", + if o.config.SignozExporterOptions != nil { + // https://signoz.io/docs/instrumentation/golang/#instrumentation-of-a-sample-golang-application + // https://signoz.io/blog/distributed-tracing-golang/ + metricOpts = append( + metricOpts, + otlpmetricgrpc.WithEndpoint( + o.config.SignozExporterOptions.OTLPEndpoint, + ), + otlpmetricgrpc.WithHeaders( + o.config.SignozExporterOptions.OTLPHeaders, + ), ) - } - exporters = append(exporters, prometheusExporter) + // send otel traces to jaeger builtin collector endpoint (default grpc port: 4317) + // https://opentelemetry.io/docs/collector/ + exporter, err := otlpmetricgrpc.New(ctx, metricOpts...) + if err != nil { + return nil, errors.WrapIf( + err, + "failed to create otlpmetric exporter for signoz", + ) + } + + signozExporter := metric.NewPeriodicReader( + exporter, + // Default is 1m. Set to 3s for demonstrative purposes. + metric.WithInterval(3*time.Second)) + + exporters = append(exporters, signozExporter) + } else { + // https://prometheus.io/docs/prometheus/latest/getting_started/ + // https://prometheus.io/docs/guides/go-application/ + // prometheus exporter will collect otel metrics in prometheus registry + // all prometheus exporters will add to a singleton `prometheus.DefaultRegisterer` registry in newConfig method and this registry will use via `promhttp.Handler` through http endpoint on `/metrics` and calls `Collect` on prometheus Reader interface inner signature prometheus.DefaultRegisterer + prometheusExporter, err := prometheus.New() + if err != nil { + return nil, errors.WrapIf( + err, + "error creating prometheus exporter", + ) + } + exporters = append(exporters, prometheusExporter) + } } else { for _, oltpProvider := range o.config.OTLPProviders { if !oltpProvider.Enabled { diff --git a/internal/pkg/otel/metrics/metrics_options.go b/internal/pkg/otel/metrics/metrics_options.go index 9c8d0977..a0536676 100644 --- a/internal/pkg/otel/metrics/metrics_options.go +++ b/internal/pkg/otel/metrics/metrics_options.go @@ -28,6 +28,7 @@ type MetricsOptions struct { OTLPProviders []OTLPProvider `mapstructure:"otlpProviders"` ElasticApmExporterOptions *OTLPProvider `mapstructure:"elasticApmExporterOptions"` UptraceExporterOptions *OTLPProvider `mapstructure:"uptraceExporterOptions"` + SignozExporterOptions *OTLPProvider `mapstructure:"signozExporterOptions"` } func ProvideMetricsConfig( diff --git a/internal/pkg/otel/tracing/tracing.go b/internal/pkg/otel/tracing/tracing.go index c216f6cc..fa013169 100644 --- a/internal/pkg/otel/tracing/tracing.go +++ b/internal/pkg/otel/tracing/tracing.go @@ -122,7 +122,7 @@ func (o *TracingOpenTelemetry) initTracer( provider := tracesdk.NewTracerProvider(opts...) - // Register our TracerProvider as the global so any imported + // Register our tracerProvider as the global so any imported // instrumentation in the future will default to using it. otel.SetTracerProvider(provider) o.provider = provider @@ -189,6 +189,34 @@ func (o *TracingOpenTelemetry) configExporters() ([]tracesdk.SpanExporter, error exporters = append(exporters, jaegerTraceExporter) } + // https://medium.com/adevinta-tech-blog/distributed-tracing-with-opentelemetry-in-your-go-python-microservices-1782cd0a1e77 + // https://grafana.com/docs/tempo/latest/getting-started/ + if o.config.TempoExporterOptions != nil { + traceOpts = append( + traceOpts, + otlptracegrpc.WithEndpoint( + o.config.TempoExporterOptions.OTLPEndpoint, + ), + otlptracegrpc.WithHeaders( + o.config.TempoExporterOptions.OTLPHeaders, + ), + ) + + // send otel traces to jaeger builtin collector endpoint (default grpc port: 4317) + // https://opentelemetry.io/docs/collector/ + grafanaTempoTraceExporter, err := otlptracegrpc.New( + ctx, + traceOpts...) + if err != nil { + return nil, errors.WrapIf( + err, + "failed to create oltptrace exporter for grafana-tempo", + ) + } + + exporters = append(exporters, grafanaTempoTraceExporter) + } + if o.config.ZipkinExporterOptions != nil { zipkinExporter, err := zipkin.New( o.config.ZipkinExporterOptions.Url, @@ -257,6 +285,32 @@ func (o *TracingOpenTelemetry) configExporters() ([]tracesdk.SpanExporter, error exporters = append(exporters, uptraceExporter) } + if o.config.SignozExporterOptions != nil { + // https://signoz.io/docs/instrumentation/golang/#instrumentation-of-a-sample-golang-application + // https://signoz.io/blog/distributed-tracing-golang/ + traceOpts = append( + traceOpts, + otlptracegrpc.WithEndpoint( + o.config.SignozExporterOptions.OTLPEndpoint, + ), + otlptracegrpc.WithHeaders( + o.config.SignozExporterOptions.OTLPHeaders, + ), + ) + + // send otel traces to jaeger builtin collector endpoint (default grpc port: 4317) + // https://opentelemetry.io/docs/collector/ + signozExporter, err := otlptracegrpc.New(ctx, traceOpts...) + if err != nil { + return nil, errors.WrapIf( + err, + "failed to create oltptrace exporter for signoz", + ) + } + + exporters = append(exporters, signozExporter) + } + if o.config.UseStdout { stdExporter, err := stdouttrace.New( stdouttrace.WithWriter( diff --git a/internal/pkg/otel/tracing/tracing_options.go b/internal/pkg/otel/tracing/tracing_options.go index 04259c73..fbebbf3a 100644 --- a/internal/pkg/otel/tracing/tracing_options.go +++ b/internal/pkg/otel/tracing/tracing_options.go @@ -26,6 +26,8 @@ type TracingOptions struct { JaegerExporterOptions *OTLPProvider `mapstructure:"jaegerExporterOptions"` ElasticApmExporterOptions *OTLPProvider `mapstructure:"elasticApmExporterOptions"` UptraceExporterOptions *OTLPProvider `mapstructure:"uptraceExporterOptions"` + SignozExporterOptions *OTLPProvider `mapstructure:"signozExporterOptions"` + TempoExporterOptions *OTLPProvider `mapstructure:"tempoExporterOptions"` UseStdout bool `mapstructure:"useStdout"` UseOTLP bool `mapstructure:"useOTLP"` OTLPProviders []OTLPProvider `mapstructure:"otlpProviders"` diff --git a/internal/services/catalog_read_service/config/config.go b/internal/services/catalog_read_service/config/config.go index e265914d..6ea4dc98 100644 --- a/internal/services/catalog_read_service/config/config.go +++ b/internal/services/catalog_read_service/config/config.go @@ -22,7 +22,7 @@ func NewConfig(env environemnt.Environment) (*Config, error) { type AppOptions struct { DeliveryType string `mapstructure:"deliveryType" env:"DeliveryType"` - ServiceName string `mapstructure:"serviceName" env:"ServiceName"` + ServiceName string `mapstructure:"serviceName" env:"serviceName"` } func (cfg *AppOptions) GetMicroserviceNameUpper() string { diff --git a/internal/services/catalog_read_service/go.mod b/internal/services/catalog_read_service/go.mod index dd54f172..5540387e 100644 --- a/internal/services/catalog_read_service/go.mod +++ b/internal/services/catalog_read_service/go.mod @@ -16,7 +16,7 @@ require ( github.com/mehdihadeli/go-mediatr v1.1.10 github.com/michaelklishin/rabbit-hole v1.5.0 github.com/pterm/pterm v0.12.69 - github.com/redis/go-redis/v9 v9.2.0 + github.com/redis/go-redis/v9 v9.2.1 github.com/satori/go.uuid v1.2.0 github.com/smartystreets/goconvey v1.8.1 github.com/spf13/cobra v1.7.0 @@ -24,9 +24,9 @@ require ( github.com/swaggo/echo-swagger v1.4.1 github.com/swaggo/swag v1.16.2 go.mongodb.org/mongo-driver v1.12.1 - go.opentelemetry.io/otel v1.18.0 - go.opentelemetry.io/otel/metric v1.18.0 - go.opentelemetry.io/otel/trace v1.18.0 + go.opentelemetry.io/otel v1.19.0 + go.opentelemetry.io/otel/metric v1.19.0 + go.opentelemetry.io/otel/trace v1.19.0 go.uber.org/fx v1.20.0 ) @@ -140,8 +140,8 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect - github.com/prometheus/client_golang v1.16.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/rabbitmq/amqp091-go v1.8.1 // indirect @@ -150,7 +150,7 @@ require ( github.com/rivo/uniseg v0.4.4 // indirect github.com/samber/lo v1.38.1 // indirect github.com/sergi/go-diff v1.2.0 // indirect - github.com/shirou/gopsutil/v3 v3.23.8 // indirect + github.com/shirou/gopsutil/v3 v3.23.9 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smarty/assertions v1.15.0 // indirect @@ -162,19 +162,19 @@ require ( github.com/stretchr/objx v0.5.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/swaggo/files/v2 v2.0.0 // indirect - github.com/testcontainers/testcontainers-go v0.24.1 // indirect + github.com/testcontainers/testcontainers-go v0.25.0 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect github.com/uptrace/bun v1.1.16 // indirect github.com/uptrace/bun/driver/pgdriver v1.1.16 // indirect - github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2 // indirect - github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 // indirect - github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 // indirect + github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.3 // indirect + github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3 // indirect + github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.27.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect - github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.0 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect @@ -188,21 +188,20 @@ require ( github.com/yudai/gojsondiff v1.0.0 // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect - go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 // indirect - go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 // indirect - go.opentelemetry.io/contrib/instrumentation/host v0.44.0 // indirect - go.opentelemetry.io/contrib/propagators/ot v1.19.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/zipkin v1.18.0 // indirect - go.opentelemetry.io/otel/sdk v1.18.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect + go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.45.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0 // indirect + go.opentelemetry.io/contrib/instrumentation/host v0.45.0 // indirect + go.opentelemetry.io/contrib/propagators/ot v1.20.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/zipkin v1.19.0 // indirect + go.opentelemetry.io/otel/sdk v1.19.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.19.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/dig v1.17.0 // indirect go.uber.org/multierr v1.11.0 // indirect diff --git a/internal/services/catalog_read_service/go.sum b/internal/services/catalog_read_service/go.sum index f8aa2c38..2bd81eec 100644 --- a/internal/services/catalog_read_service/go.sum +++ b/internal/services/catalog_read_service/go.sum @@ -325,8 +325,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 h1:gpptm606MZYGaMHMsB4Srmb6EbW/IVHnt04rcMXnkBQ= -github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ= +github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -554,8 +554,8 @@ github.com/onsi/ginkgo/v2 v2.12.1/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xl github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/onsi/gomega v1.28.0 h1:i2rg/p9n/UqIDAMFUJ6qIUUMcsqOuUHgbpbu235Vr1c= +github.com/onsi/gomega v1.28.0/go.mod h1:A1H2JE76sI14WIP57LMKj7FVfCHx3g3BcZVjJG8bjX8= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -586,11 +586,11 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= @@ -611,8 +611,8 @@ github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJu github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc= github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ= github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= -github.com/redis/go-redis/v9 v9.2.0 h1:zwMdX0A4eVzse46YN18QhuDiM4uf3JmkOB4VZrdt5uI= -github.com/redis/go-redis/v9 v9.2.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= +github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -634,8 +634,8 @@ github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvW github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= -github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/shirou/gopsutil/v3 v3.23.9 h1:ZI5bWVeu2ep4/DIxB4U9okeYJ7zp/QLTO4auRb/ty/E= +github.com/shirou/gopsutil/v3 v3.23.9/go.mod h1:x/NWSb71eMcjFIO0vhyGW5nZ7oSIgVjrCnADckb85GA= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= @@ -700,8 +700,8 @@ github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0J github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04= github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/testcontainers/testcontainers-go v0.24.1 h1:gJdZuQIVWnMJTo+CmQMEP7/CAagNk/0jbcUPn3OWvD8= -github.com/testcontainers/testcontainers-go v0.24.1/go.mod h1:MGBiAkCm86yXQoCiipmQCqZLVdk1uFqtMqaU1Or0MRk= +github.com/testcontainers/testcontainers-go v0.25.0 h1:erH6cQjsaJrH+rJDU9qIf89KFdhK0Bft0aEZHlYC3Vs= +github.com/testcontainers/testcontainers-go v0.25.0/go.mod h1:4sC9SiJyzD1XFi59q8umTQYWxnkweEc5OjVtTUlJzqQ= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= @@ -713,12 +713,12 @@ github.com/uptrace/bun v1.1.16 h1:cn9cgEMFwcyYRsQLfxCRMUxyK1WaHwOVrR3TvzEFZ/A= github.com/uptrace/bun v1.1.16/go.mod h1:7HnsMRRvpLFUcquJxp22JO8PsWKpFQO/gNXqqsuGWg8= github.com/uptrace/bun/driver/pgdriver v1.1.16 h1:b/NiSXk6Ldw7KLfMLbOqIkm4odHd7QiNOCPLqPFJjK4= github.com/uptrace/bun/driver/pgdriver v1.1.16/go.mod h1:Rmfbc+7lx1z/umjMyAxkOHK81LgnGj71XC5YpA6k1vU= -github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2 h1:s3quVevwQlgEMCkvscS/VHo92amtyMzRfcuOZqfevrM= -github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2/go.mod h1:IJLBT7ItgUACTEoq6BEw/9HwHWL4BiPirYgKhZS83Lg= -github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 h1:CNznWHkrbA6o1q2H/BsH4tIHf4zbKNtndeoV+AH8z0U= -github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2/go.mod h1:7YSrHCmYPHIXjTWnKSU7EGT0TFEcm3WwSeQquwCGg38= -github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 h1:uyrW06oJi4iWvhjPLVfk4qrSP2Zm0AMozKKDmp6i4pE= -github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2/go.mod h1:PMAs2dNxP55lgt6xu0if+Jasm6s+Xpmqn6ev1NyDfnI= +github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.3 h1:m5eNyOhch/7tyK6aN6eRRpNoD1vM8PNh64dA05X22Js= +github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.3/go.mod h1:APPUXm9BbpH7NFkfpbw04raZSitzl19/3NOCu0rbI4E= +github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3 h1:LyGS9cIZV0YVhE81zwfMhIE2l2flcj3wn5IoK4VkbWA= +github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3/go.mod h1:RvCYhPchLhvQ9l9C9goblbgO7BaKt597kBMf5mgKyo0= +github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3 h1:2na5W81H38Z4qXCQCuzlcdSMiTWgPJ6XeZIArq6VIJE= +github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3/go.mod h1:9IVEh9mPv3NwFf99dVLX15FqVgdpZJ8RMDo/Cr0vK74= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -730,8 +730,8 @@ github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+ github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= -github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/msgpack/v5 v5.4.0 h1:hRM0digJwyR6vll33NNAwCFguy5JuBD6jxDmQP3l608= +github.com/vmihailenco/msgpack/v5 v5.4.0/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= @@ -783,44 +783,40 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 h1:9n9+SOwuCyZ0L8SbQYjZ5H+GKojHN3Kl8pBLwBUQqhk= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0/go.mod h1:Wa9/q2K5L+ftWke2iekGNqVzwBWqyhI5OhtHKU7Qe04= -go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 h1:M5oKw7m89PAciR2j41n5Zq9rShK14iUadvCRy7nkSIo= -go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0/go.mod h1:JH6FxBlkXo/cYoU/m65W5dOQ6sqPL+jHtSJaSE7/+XQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 h1:b8xjZxHbLrXAum4SxJd1Rlm7Y/fKaB+6ACI7/e5EfSA= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0/go.mod h1:1ei0a32xOGkFoySu7y1DAHfcuIhC0pNZpvY2huXuMy4= -go.opentelemetry.io/contrib/instrumentation/host v0.44.0 h1:SNqDjPpQmwFYvDipyJJxDbU5zKNWiYSMii864ubzIuQ= -go.opentelemetry.io/contrib/instrumentation/host v0.44.0/go.mod h1:bZcqg3yy0riQLNkx8dJWV4J3tbfL+6LQ5lIbI+vmarE= -go.opentelemetry.io/contrib/propagators/b3 v1.19.0 h1:ulz44cpm6V5oAeg5Aw9HyqGFMS6XM7untlMEhD7YzzA= -go.opentelemetry.io/contrib/propagators/b3 v1.19.0/go.mod h1:OzCmE2IVS+asTI+odXQstRGVfXQ4bXv9nMBRK0nNyqQ= -go.opentelemetry.io/contrib/propagators/ot v1.19.0 h1:vODRLMlKN4ApM8ri0UDk8nnEeISuwxpf67sE7PmOHhE= -go.opentelemetry.io/contrib/propagators/ot v1.19.0/go.mod h1:S2Uc7th2ZmLiHu0lrCmDCgTQ/y5Nbbis+TNjR1jjm4Q= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 h1:k0k7hFNDd8K4iOMJXj7s8sHaC4mhTlAeppRmZXLgZ6k= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 h1:HgbDTD8pioFdY3NRc/YCvsWjqQPtweGyXxa32LgnTOw= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0/go.mod h1:tmvt/yK5Es5d6lHYWerLSOna8lCEfrBVX/a9M0ggqss= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 h1:IAtl+7gua134xcV3NieDhJHjjOVeJhXAnYf/0hswjUY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0/go.mod h1:w+pXobnBzh95MNIkeIuAKcHe/Uu/CX2PKIvBP6ipKRA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32ay7mJG2leczfREEhoW3VfSZIvHaB+gvVo1o8DQ8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 h1:XzjGkawtAXs20Y+s6k1GNDMBsMDOV28TOT8cxmE42qM= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0/go.mod h1:HAomEgjcKZk3VJ+HHdHLnhZXeGqdzPxxNTdKYRopUXY= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes= -go.opentelemetry.io/otel/exporters/zipkin v1.18.0 h1:ZqrHgvega5NIiScTiVrtpZSpEmjUdwzkhuuCEIMAp+s= -go.opentelemetry.io/otel/exporters/zipkin v1.18.0/go.mod h1:C80yIYcSceQipAZb4Ah11EE/yERlyc1MtqJG2xP7p+s= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.45.0 h1:bldpPC7XAv7f7LKTwNfRkNdzRhjtXaWybZFFa16dAb8= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.45.0/go.mod h1:xhkNpJG3D+kmuaciNTco7cdK27Fb77J9Iqcq5CMe4Y8= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0 h1:RsQi0qJ2imFfCvZabqzM9cNXBG8k6gXMv1A0cXRmH6A= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0/go.mod h1:vsh3ySueQCiKPxFLvjWC4Z135gIa34TQ/NSqkDTZYUM= +go.opentelemetry.io/contrib/instrumentation/host v0.45.0 h1:1uzNKJDqZ6y6F5J6aKWgJjRREpKiGhBvKHlWon/bqB4= +go.opentelemetry.io/contrib/instrumentation/host v0.45.0/go.mod h1:vlqPvzDsmB4+jlERxBRXsdLCD6Q0LoBzxHqNXp3qvG4= +go.opentelemetry.io/contrib/propagators/ot v1.20.0 h1:duH7mgL6VGQH7e7QEAVOFkCQXWpCb4PjTtrhdrYrJRQ= +go.opentelemetry.io/contrib/propagators/ot v1.20.0/go.mod h1:gijQzxOq0JLj9lyZhTvqjDddGV/zaNagpPIn+2r8CEI= +go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= +go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 h1:NmnYCiR0qNufkldjVvyQfZTHSdzeHoZ41zggMsdMcLM= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0/go.mod h1:UVAO61+umUsHLtYb8KXXRoHtxUkdOPkYidzW3gipRLQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0 h1:jwV9iQdvp38fxXi8ZC+lNpxjK16MRcZlpDYvbuO1FiA= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0/go.mod h1:f3bYiqNqhoPxkvI2LrXqQVC546K7BuRDL/kKuxkujhA= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0 h1:4jJuoeOo9W6hZnz+r046fyoH5kykZPRvKfUXJVfMpB0= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0/go.mod h1:/MtYTE1SfC2QIcE0bDot6fIX+h+WvXjgTqgn9P0LNPE= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 h1:Nw7Dv4lwvGrI68+wULbcq7su9K2cebeCUrDjVrUJHxM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0/go.mod h1:1MsF6Y7gTqosgoZvHlzcaaM8DIMNZgJh87ykokoNH7Y= +go.opentelemetry.io/otel/exporters/zipkin v1.19.0 h1:EGY0h5mGliP9o/nIkVuLI0vRiQqmsYOcbwCuotksO1o= +go.opentelemetry.io/otel/exporters/zipkin v1.19.0/go.mod h1:JQgTGJP11yi3o4GHzIWYodhPisxANdqxF1eHwDSnJrI= +go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= +go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k= +go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY= +go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= +go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= diff --git a/internal/services/catalog_write_service/config/app_options.go b/internal/services/catalog_write_service/config/app_options.go index ff1470f7..b2e3ce78 100644 --- a/internal/services/catalog_write_service/config/app_options.go +++ b/internal/services/catalog_write_service/config/app_options.go @@ -12,7 +12,7 @@ import ( type AppOptions struct { DeliveryType string `mapstructure:"deliveryType" env:"DeliveryType"` - ServiceName string `mapstructure:"serviceName" env:"ServiceName"` + ServiceName string `mapstructure:"serviceName" env:"serviceName"` } func NewAppOptions(environment environemnt.Environment) (*AppOptions, error) { diff --git a/internal/services/catalog_write_service/config/config.development.json b/internal/services/catalog_write_service/config/config.development.json index 01b23675..325aa5c2 100644 --- a/internal/services/catalog_write_service/config/config.development.json +++ b/internal/services/catalog_write_service/config/config.development.json @@ -59,6 +59,10 @@ "otlpEndpoint": "localhost:4320", "enabled": true }, + "tempoExporterOptions": { + "otlpEndpoint": "localhost:4322", + "enabled": true + }, "zipkinExporterOptions": { "url": "http://localhost:9411/api/v2/spans" }, @@ -78,6 +82,16 @@ "otlpHeaders": { "Authorization": "Bearer ${ELASTIC_APM_SECRET_TOKEN}" } + }, + { + "name": "signoz", + "enabled": false, + "otlpEndpoint": "localhost:4317" + }, + { + "name": "grafana-tempo", + "enabled": false, + "otlpEndpoint": "localhost:4322" } ] }, diff --git a/internal/services/catalog_write_service/go.mod b/internal/services/catalog_write_service/go.mod index d687ac8c..251ddbc2 100644 --- a/internal/services/catalog_write_service/go.mod +++ b/internal/services/catalog_write_service/go.mod @@ -19,16 +19,16 @@ require ( github.com/mehdihadeli/go-mediatr v1.1.10 github.com/michaelklishin/rabbit-hole v1.5.0 github.com/onsi/ginkgo v1.16.5 - github.com/onsi/gomega v1.27.10 + github.com/onsi/gomega v1.28.0 github.com/pterm/pterm v0.12.69 github.com/satori/go.uuid v1.2.0 github.com/spf13/cobra v1.7.0 github.com/stretchr/testify v1.8.4 github.com/swaggo/echo-swagger v1.4.1 github.com/swaggo/swag v1.16.2 - go.opentelemetry.io/otel v1.18.0 - go.opentelemetry.io/otel/metric v1.18.0 - go.opentelemetry.io/otel/trace v1.18.0 + go.opentelemetry.io/otel v1.19.0 + go.opentelemetry.io/otel/metric v1.19.0 + go.opentelemetry.io/otel/trace v1.19.0 go.uber.org/fx v1.20.0 google.golang.org/grpc v1.58.2 gopkg.in/khaiql/dbcleaner.v2 v2.3.0 @@ -148,31 +148,31 @@ require ( github.com/rabbitmq/amqp091-go v1.8.1 // indirect github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 // indirect - github.com/redis/go-redis/v9 v9.2.0 // indirect + github.com/redis/go-redis/v9 v9.2.1 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/samber/lo v1.38.1 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/sergi/go-diff v1.2.0 // indirect - github.com/shirou/gopsutil/v3 v3.23.8 // indirect + github.com/shirou/gopsutil/v3 v3.23.9 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/viper v1.16.0 // indirect github.com/stretchr/objx v0.5.1 // indirect github.com/swaggo/files/v2 v2.0.0 // indirect - github.com/testcontainers/testcontainers-go v0.24.1 // indirect + github.com/testcontainers/testcontainers-go v0.25.0 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect github.com/uptrace/bun v1.1.16 // indirect github.com/uptrace/bun/driver/pgdriver v1.1.16 // indirect - github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2 // indirect - github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 // indirect - github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 // indirect + github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.3 // indirect + github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3 // indirect + github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.27.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect - github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.0 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect @@ -187,21 +187,20 @@ require ( github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect go.mongodb.org/mongo-driver v1.12.1 // indirect - go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 // indirect - go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 // indirect - go.opentelemetry.io/contrib/instrumentation/host v0.44.0 // indirect - go.opentelemetry.io/contrib/propagators/ot v1.19.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/zipkin v1.18.0 // indirect - go.opentelemetry.io/otel/sdk v1.18.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect + go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.45.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0 // indirect + go.opentelemetry.io/contrib/instrumentation/host v0.45.0 // indirect + go.opentelemetry.io/contrib/propagators/ot v1.20.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/zipkin v1.19.0 // indirect + go.opentelemetry.io/otel/sdk v1.19.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.19.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/dig v1.17.0 // indirect go.uber.org/multierr v1.11.0 // indirect @@ -234,8 +233,8 @@ 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/prometheus/client_golang v1.16.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/spf13/afero v1.10.0 // indirect github.com/spf13/cast v1.5.1 // indirect diff --git a/internal/services/catalog_write_service/go.sum b/internal/services/catalog_write_service/go.sum index 5e572a44..56ac8692 100644 --- a/internal/services/catalog_write_service/go.sum +++ b/internal/services/catalog_write_service/go.sum @@ -347,8 +347,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 h1:gpptm606MZYGaMHMsB4Srmb6EbW/IVHnt04rcMXnkBQ= -github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ= +github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -576,8 +576,8 @@ github.com/onsi/ginkgo/v2 v2.12.1/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xl github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/onsi/gomega v1.28.0 h1:i2rg/p9n/UqIDAMFUJ6qIUUMcsqOuUHgbpbu235Vr1c= +github.com/onsi/gomega v1.28.0/go.mod h1:A1H2JE76sI14WIP57LMKj7FVfCHx3g3BcZVjJG8bjX8= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -615,11 +615,11 @@ github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3g github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/pressly/goose/v3 v3.15.0 h1:6tY5aDqFknY6VZkorFGgZtWygodZQxfmmEF4rqyJW9k= github.com/pressly/goose/v3 v3.15.0/go.mod h1:LlIo3zGccjb/YUgG+Svdb9Er14vefRdlDI7URCDrwYo= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= @@ -640,8 +640,8 @@ github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJu github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc= github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ= github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= -github.com/redis/go-redis/v9 v9.2.0 h1:zwMdX0A4eVzse46YN18QhuDiM4uf3JmkOB4VZrdt5uI= -github.com/redis/go-redis/v9 v9.2.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= +github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -667,8 +667,8 @@ github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= -github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/shirou/gopsutil/v3 v3.23.9 h1:ZI5bWVeu2ep4/DIxB4U9okeYJ7zp/QLTO4auRb/ty/E= +github.com/shirou/gopsutil/v3 v3.23.9/go.mod h1:x/NWSb71eMcjFIO0vhyGW5nZ7oSIgVjrCnADckb85GA= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= @@ -729,10 +729,10 @@ github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0J github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04= github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/testcontainers/testcontainers-go v0.24.1 h1:gJdZuQIVWnMJTo+CmQMEP7/CAagNk/0jbcUPn3OWvD8= -github.com/testcontainers/testcontainers-go v0.24.1/go.mod h1:MGBiAkCm86yXQoCiipmQCqZLVdk1uFqtMqaU1Or0MRk= -github.com/testcontainers/testcontainers-go/modules/postgres v0.24.1 h1:lSJLORAjkj8PoiZef+KoziJbhpRmL1ELzJXQQ8L3s1U= -github.com/testcontainers/testcontainers-go/modules/postgres v0.24.1/go.mod h1:QG4rCYFma/K7CbAFtrqCIn87EI6bNRWaW+Ebt4UV2WA= +github.com/testcontainers/testcontainers-go v0.25.0 h1:erH6cQjsaJrH+rJDU9qIf89KFdhK0Bft0aEZHlYC3Vs= +github.com/testcontainers/testcontainers-go v0.25.0/go.mod h1:4sC9SiJyzD1XFi59q8umTQYWxnkweEc5OjVtTUlJzqQ= +github.com/testcontainers/testcontainers-go/modules/postgres v0.25.0 h1:8WNK1Edo9ohRYPrDCXWdoVY2cbg/oFh9y5uWZGSBESo= +github.com/testcontainers/testcontainers-go/modules/postgres v0.25.0/go.mod h1:XpwOhyUXheL31hz73L8be8maW1rQq8H48x5qZeHtYr0= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= @@ -744,12 +744,12 @@ github.com/uptrace/bun v1.1.16 h1:cn9cgEMFwcyYRsQLfxCRMUxyK1WaHwOVrR3TvzEFZ/A= github.com/uptrace/bun v1.1.16/go.mod h1:7HnsMRRvpLFUcquJxp22JO8PsWKpFQO/gNXqqsuGWg8= github.com/uptrace/bun/driver/pgdriver v1.1.16 h1:b/NiSXk6Ldw7KLfMLbOqIkm4odHd7QiNOCPLqPFJjK4= github.com/uptrace/bun/driver/pgdriver v1.1.16/go.mod h1:Rmfbc+7lx1z/umjMyAxkOHK81LgnGj71XC5YpA6k1vU= -github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2 h1:s3quVevwQlgEMCkvscS/VHo92amtyMzRfcuOZqfevrM= -github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2/go.mod h1:IJLBT7ItgUACTEoq6BEw/9HwHWL4BiPirYgKhZS83Lg= -github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 h1:CNznWHkrbA6o1q2H/BsH4tIHf4zbKNtndeoV+AH8z0U= -github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2/go.mod h1:7YSrHCmYPHIXjTWnKSU7EGT0TFEcm3WwSeQquwCGg38= -github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 h1:uyrW06oJi4iWvhjPLVfk4qrSP2Zm0AMozKKDmp6i4pE= -github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2/go.mod h1:PMAs2dNxP55lgt6xu0if+Jasm6s+Xpmqn6ev1NyDfnI= +github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.3 h1:m5eNyOhch/7tyK6aN6eRRpNoD1vM8PNh64dA05X22Js= +github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.3/go.mod h1:APPUXm9BbpH7NFkfpbw04raZSitzl19/3NOCu0rbI4E= +github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3 h1:LyGS9cIZV0YVhE81zwfMhIE2l2flcj3wn5IoK4VkbWA= +github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3/go.mod h1:RvCYhPchLhvQ9l9C9goblbgO7BaKt597kBMf5mgKyo0= +github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3 h1:2na5W81H38Z4qXCQCuzlcdSMiTWgPJ6XeZIArq6VIJE= +github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3/go.mod h1:9IVEh9mPv3NwFf99dVLX15FqVgdpZJ8RMDo/Cr0vK74= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -761,8 +761,8 @@ github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+ github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= -github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/msgpack/v5 v5.4.0 h1:hRM0digJwyR6vll33NNAwCFguy5JuBD6jxDmQP3l608= +github.com/vmihailenco/msgpack/v5 v5.4.0/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= @@ -817,44 +817,40 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 h1:9n9+SOwuCyZ0L8SbQYjZ5H+GKojHN3Kl8pBLwBUQqhk= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0/go.mod h1:Wa9/q2K5L+ftWke2iekGNqVzwBWqyhI5OhtHKU7Qe04= -go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 h1:M5oKw7m89PAciR2j41n5Zq9rShK14iUadvCRy7nkSIo= -go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0/go.mod h1:JH6FxBlkXo/cYoU/m65W5dOQ6sqPL+jHtSJaSE7/+XQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 h1:b8xjZxHbLrXAum4SxJd1Rlm7Y/fKaB+6ACI7/e5EfSA= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0/go.mod h1:1ei0a32xOGkFoySu7y1DAHfcuIhC0pNZpvY2huXuMy4= -go.opentelemetry.io/contrib/instrumentation/host v0.44.0 h1:SNqDjPpQmwFYvDipyJJxDbU5zKNWiYSMii864ubzIuQ= -go.opentelemetry.io/contrib/instrumentation/host v0.44.0/go.mod h1:bZcqg3yy0riQLNkx8dJWV4J3tbfL+6LQ5lIbI+vmarE= -go.opentelemetry.io/contrib/propagators/b3 v1.19.0 h1:ulz44cpm6V5oAeg5Aw9HyqGFMS6XM7untlMEhD7YzzA= -go.opentelemetry.io/contrib/propagators/b3 v1.19.0/go.mod h1:OzCmE2IVS+asTI+odXQstRGVfXQ4bXv9nMBRK0nNyqQ= -go.opentelemetry.io/contrib/propagators/ot v1.19.0 h1:vODRLMlKN4ApM8ri0UDk8nnEeISuwxpf67sE7PmOHhE= -go.opentelemetry.io/contrib/propagators/ot v1.19.0/go.mod h1:S2Uc7th2ZmLiHu0lrCmDCgTQ/y5Nbbis+TNjR1jjm4Q= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0 h1:k0k7hFNDd8K4iOMJXj7s8sHaC4mhTlAeppRmZXLgZ6k= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.41.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0 h1:HgbDTD8pioFdY3NRc/YCvsWjqQPtweGyXxa32LgnTOw= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.41.0/go.mod h1:tmvt/yK5Es5d6lHYWerLSOna8lCEfrBVX/a9M0ggqss= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 h1:IAtl+7gua134xcV3NieDhJHjjOVeJhXAnYf/0hswjUY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0/go.mod h1:w+pXobnBzh95MNIkeIuAKcHe/Uu/CX2PKIvBP6ipKRA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32ay7mJG2leczfREEhoW3VfSZIvHaB+gvVo1o8DQ8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 h1:XzjGkawtAXs20Y+s6k1GNDMBsMDOV28TOT8cxmE42qM= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0/go.mod h1:HAomEgjcKZk3VJ+HHdHLnhZXeGqdzPxxNTdKYRopUXY= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes= -go.opentelemetry.io/otel/exporters/zipkin v1.18.0 h1:ZqrHgvega5NIiScTiVrtpZSpEmjUdwzkhuuCEIMAp+s= -go.opentelemetry.io/otel/exporters/zipkin v1.18.0/go.mod h1:C80yIYcSceQipAZb4Ah11EE/yERlyc1MtqJG2xP7p+s= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.45.0 h1:bldpPC7XAv7f7LKTwNfRkNdzRhjtXaWybZFFa16dAb8= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.45.0/go.mod h1:xhkNpJG3D+kmuaciNTco7cdK27Fb77J9Iqcq5CMe4Y8= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0 h1:RsQi0qJ2imFfCvZabqzM9cNXBG8k6gXMv1A0cXRmH6A= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0/go.mod h1:vsh3ySueQCiKPxFLvjWC4Z135gIa34TQ/NSqkDTZYUM= +go.opentelemetry.io/contrib/instrumentation/host v0.45.0 h1:1uzNKJDqZ6y6F5J6aKWgJjRREpKiGhBvKHlWon/bqB4= +go.opentelemetry.io/contrib/instrumentation/host v0.45.0/go.mod h1:vlqPvzDsmB4+jlERxBRXsdLCD6Q0LoBzxHqNXp3qvG4= +go.opentelemetry.io/contrib/propagators/ot v1.20.0 h1:duH7mgL6VGQH7e7QEAVOFkCQXWpCb4PjTtrhdrYrJRQ= +go.opentelemetry.io/contrib/propagators/ot v1.20.0/go.mod h1:gijQzxOq0JLj9lyZhTvqjDddGV/zaNagpPIn+2r8CEI= +go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= +go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 h1:NmnYCiR0qNufkldjVvyQfZTHSdzeHoZ41zggMsdMcLM= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0/go.mod h1:UVAO61+umUsHLtYb8KXXRoHtxUkdOPkYidzW3gipRLQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0 h1:jwV9iQdvp38fxXi8ZC+lNpxjK16MRcZlpDYvbuO1FiA= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0/go.mod h1:f3bYiqNqhoPxkvI2LrXqQVC546K7BuRDL/kKuxkujhA= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0 h1:4jJuoeOo9W6hZnz+r046fyoH5kykZPRvKfUXJVfMpB0= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0/go.mod h1:/MtYTE1SfC2QIcE0bDot6fIX+h+WvXjgTqgn9P0LNPE= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 h1:Nw7Dv4lwvGrI68+wULbcq7su9K2cebeCUrDjVrUJHxM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0/go.mod h1:1MsF6Y7gTqosgoZvHlzcaaM8DIMNZgJh87ykokoNH7Y= +go.opentelemetry.io/otel/exporters/zipkin v1.19.0 h1:EGY0h5mGliP9o/nIkVuLI0vRiQqmsYOcbwCuotksO1o= +go.opentelemetry.io/otel/exporters/zipkin v1.19.0/go.mod h1:JQgTGJP11yi3o4GHzIWYodhPisxANdqxF1eHwDSnJrI= +go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= +go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k= +go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY= +go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= +go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= diff --git a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go index 6fb80faf..b057380e 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go @@ -66,7 +66,10 @@ func (ep *getProductsEndpoint) handler() echo.HandlerFunc { "[getProductsEndpoint_handler.Bind] error in the binding request", ) ep.Logger.Errorf( - fmt.Sprintf("[getProductsEndpoint_handler.Bind] err: %v", badRequestErr), + fmt.Sprintf( + "[getProductsEndpoint_handler.Bind] err: %v", + badRequestErr, + ), ) return badRequestErr } @@ -85,7 +88,12 @@ func (ep *getProductsEndpoint) handler() echo.HandlerFunc { err, "[getProductsEndpoint_handler.Send] error in sending GetProducts", ) - ep.Logger.Error(fmt.Sprintf("[getProductsEndpoint_handler.Send] err: {%v}", err)) + ep.Logger.Error( + fmt.Sprintf( + "[getProductsEndpoint_handler.Send] err: {%v}", + err, + ), + ) return err } diff --git a/internal/services/order_service/go.mod b/internal/services/order_service/go.mod index 9c38edc9..a71ac28c 100644 --- a/internal/services/order_service/go.mod +++ b/internal/services/order_service/go.mod @@ -19,7 +19,7 @@ require ( github.com/mehdihadeli/go-mediatr v1.1.10 github.com/michaelklishin/rabbit-hole v1.5.0 github.com/onsi/ginkgo v1.16.5 - github.com/onsi/gomega v1.27.10 + github.com/onsi/gomega v1.28.0 github.com/pterm/pterm v0.12.69 github.com/satori/go.uuid v1.2.0 github.com/spf13/cobra v1.7.0 @@ -27,11 +27,11 @@ require ( github.com/swaggo/echo-swagger v1.4.1 github.com/swaggo/swag v1.16.2 go.mongodb.org/mongo-driver v1.12.1 - go.opentelemetry.io/otel v1.18.0 - go.opentelemetry.io/otel/metric v1.18.0 - go.opentelemetry.io/otel/trace v1.18.0 + go.opentelemetry.io/otel v1.19.0 + go.opentelemetry.io/otel/metric v1.19.0 + go.opentelemetry.io/otel/trace v1.19.0 go.uber.org/fx v1.20.0 - google.golang.org/grpc v1.58.1 + google.golang.org/grpc v1.58.2 google.golang.org/protobuf v1.31.0 ) @@ -44,7 +44,7 @@ require ( github.com/KyleBanks/depth v1.2.1 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/Microsoft/hcsshim v0.11.0 // indirect + github.com/Microsoft/hcsshim v0.11.1 // indirect github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 // indirect github.com/ahmetb/go-linq/v3 v3.2.0 // indirect github.com/ajg/form v1.5.1 // indirect @@ -146,22 +146,22 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect - github.com/prometheus/client_golang v1.16.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.11.1 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/rabbitmq/amqp091-go v1.8.1 // indirect github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 // indirect - github.com/redis/go-redis/v9 v9.2.0 // indirect + github.com/redis/go-redis/v9 v9.2.1 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/samber/lo v1.38.1 // indirect github.com/sanity-io/litter v1.5.5 // indirect github.com/sergi/go-diff v1.2.0 // indirect - github.com/shirou/gopsutil/v3 v3.23.8 // indirect + github.com/shirou/gopsutil/v3 v3.23.9 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/spf13/afero v1.9.5 // indirect + github.com/spf13/afero v1.10.0 // indirect github.com/spf13/cast v1.5.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect @@ -169,18 +169,19 @@ require ( github.com/stretchr/objx v0.5.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/swaggo/files/v2 v2.0.0 // indirect - github.com/testcontainers/testcontainers-go v0.24.1 // indirect + github.com/testcontainers/testcontainers-go v0.25.0 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect github.com/uptrace/bun v1.1.16 // indirect github.com/uptrace/bun/driver/pgdriver v1.1.16 // indirect - github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 // indirect - github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 // indirect + github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.3 // indirect + github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3 // indirect + github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.34.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect - github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.0 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect @@ -194,18 +195,20 @@ require ( github.com/yudai/gojsondiff v1.0.0 // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect - go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 // indirect - go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 // indirect - go.opentelemetry.io/contrib/propagators/ot v1.19.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 // indirect - go.opentelemetry.io/otel/exporters/zipkin v1.18.0 // indirect - go.opentelemetry.io/otel/sdk v1.18.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect + go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.45.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0 // indirect + go.opentelemetry.io/contrib/instrumentation/host v0.45.0 // indirect + go.opentelemetry.io/contrib/propagators/ot v1.20.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/zipkin v1.19.0 // indirect + go.opentelemetry.io/otel/sdk v1.19.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.19.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/dig v1.17.0 // indirect go.uber.org/multierr v1.11.0 // indirect diff --git a/internal/services/order_service/go.sum b/internal/services/order_service/go.sum index fe6ca576..9f1c3a91 100644 --- a/internal/services/order_service/go.sum +++ b/internal/services/order_service/go.sum @@ -83,8 +83,8 @@ github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA4 github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.11.0 h1:7EFNIY4igHEXUdj1zXgAyU3fLc7QfOKHbkldRVTBdiM= -github.com/Microsoft/hcsshim v0.11.0/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= +github.com/Microsoft/hcsshim v0.11.1 h1:hJ3s7GbWlGK4YVV92sO88BQSyF4ZLVy7/awqOlPxFbA= +github.com/Microsoft/hcsshim v0.11.1/go.mod h1:nFJmaO4Zr5Y7eADdFOpYswDDlNVbvcIJJNJLECr5JQg= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4= @@ -331,8 +331,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ= +github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -550,13 +550,13 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= -github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/ginkgo/v2 v2.12.1 h1:uHNEO1RP2SpuZApSkel9nEh1/Mu+hmQe7Q+Pepg5OYA= +github.com/onsi/ginkgo/v2 v2.12.1/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/onsi/gomega v1.28.0 h1:i2rg/p9n/UqIDAMFUJ6qIUUMcsqOuUHgbpbu235Vr1c= +github.com/onsi/gomega v1.28.0/go.mod h1:A1H2JE76sI14WIP57LMKj7FVfCHx3g3BcZVjJG8bjX8= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -589,15 +589,15 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= @@ -614,8 +614,8 @@ github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJu github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc= github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ= github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= -github.com/redis/go-redis/v9 v9.2.0 h1:zwMdX0A4eVzse46YN18QhuDiM4uf3JmkOB4VZrdt5uI= -github.com/redis/go-redis/v9 v9.2.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= +github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= @@ -639,8 +639,8 @@ github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvW github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= -github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/shirou/gopsutil/v3 v3.23.9 h1:ZI5bWVeu2ep4/DIxB4U9okeYJ7zp/QLTO4auRb/ty/E= +github.com/shirou/gopsutil/v3 v3.23.9/go.mod h1:x/NWSb71eMcjFIO0vhyGW5nZ7oSIgVjrCnADckb85GA= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= @@ -656,8 +656,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= +github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= @@ -703,8 +703,8 @@ github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04= github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8= -github.com/testcontainers/testcontainers-go v0.24.1 h1:gJdZuQIVWnMJTo+CmQMEP7/CAagNk/0jbcUPn3OWvD8= -github.com/testcontainers/testcontainers-go v0.24.1/go.mod h1:MGBiAkCm86yXQoCiipmQCqZLVdk1uFqtMqaU1Or0MRk= +github.com/testcontainers/testcontainers-go v0.25.0 h1:erH6cQjsaJrH+rJDU9qIf89KFdhK0Bft0aEZHlYC3Vs= +github.com/testcontainers/testcontainers-go v0.25.0/go.mod h1:4sC9SiJyzD1XFi59q8umTQYWxnkweEc5OjVtTUlJzqQ= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= @@ -716,10 +716,12 @@ github.com/uptrace/bun v1.1.16 h1:cn9cgEMFwcyYRsQLfxCRMUxyK1WaHwOVrR3TvzEFZ/A= github.com/uptrace/bun v1.1.16/go.mod h1:7HnsMRRvpLFUcquJxp22JO8PsWKpFQO/gNXqqsuGWg8= github.com/uptrace/bun/driver/pgdriver v1.1.16 h1:b/NiSXk6Ldw7KLfMLbOqIkm4odHd7QiNOCPLqPFJjK4= github.com/uptrace/bun/driver/pgdriver v1.1.16/go.mod h1:Rmfbc+7lx1z/umjMyAxkOHK81LgnGj71XC5YpA6k1vU= -github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 h1:CNznWHkrbA6o1q2H/BsH4tIHf4zbKNtndeoV+AH8z0U= -github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2/go.mod h1:7YSrHCmYPHIXjTWnKSU7EGT0TFEcm3WwSeQquwCGg38= -github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2 h1:uyrW06oJi4iWvhjPLVfk4qrSP2Zm0AMozKKDmp6i4pE= -github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.2/go.mod h1:PMAs2dNxP55lgt6xu0if+Jasm6s+Xpmqn6ev1NyDfnI= +github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.3 h1:m5eNyOhch/7tyK6aN6eRRpNoD1vM8PNh64dA05X22Js= +github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.3/go.mod h1:APPUXm9BbpH7NFkfpbw04raZSitzl19/3NOCu0rbI4E= +github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3 h1:LyGS9cIZV0YVhE81zwfMhIE2l2flcj3wn5IoK4VkbWA= +github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3/go.mod h1:RvCYhPchLhvQ9l9C9goblbgO7BaKt597kBMf5mgKyo0= +github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3 h1:2na5W81H38Z4qXCQCuzlcdSMiTWgPJ6XeZIArq6VIJE= +github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3/go.mod h1:9IVEh9mPv3NwFf99dVLX15FqVgdpZJ8RMDo/Cr0vK74= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -731,8 +733,8 @@ github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+ github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= -github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/msgpack/v5 v5.4.0 h1:hRM0digJwyR6vll33NNAwCFguy5JuBD6jxDmQP3l608= +github.com/vmihailenco/msgpack/v5 v5.4.0/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= @@ -783,38 +785,40 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 h1:9n9+SOwuCyZ0L8SbQYjZ5H+GKojHN3Kl8pBLwBUQqhk= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0/go.mod h1:Wa9/q2K5L+ftWke2iekGNqVzwBWqyhI5OhtHKU7Qe04= -go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0 h1:M5oKw7m89PAciR2j41n5Zq9rShK14iUadvCRy7nkSIo= -go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.44.0/go.mod h1:JH6FxBlkXo/cYoU/m65W5dOQ6sqPL+jHtSJaSE7/+XQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0 h1:b8xjZxHbLrXAum4SxJd1Rlm7Y/fKaB+6ACI7/e5EfSA= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.44.0/go.mod h1:1ei0a32xOGkFoySu7y1DAHfcuIhC0pNZpvY2huXuMy4= -go.opentelemetry.io/contrib/propagators/b3 v1.19.0 h1:ulz44cpm6V5oAeg5Aw9HyqGFMS6XM7untlMEhD7YzzA= -go.opentelemetry.io/contrib/propagators/b3 v1.19.0/go.mod h1:OzCmE2IVS+asTI+odXQstRGVfXQ4bXv9nMBRK0nNyqQ= -go.opentelemetry.io/contrib/propagators/ot v1.19.0 h1:vODRLMlKN4ApM8ri0UDk8nnEeISuwxpf67sE7PmOHhE= -go.opentelemetry.io/contrib/propagators/ot v1.19.0/go.mod h1:S2Uc7th2ZmLiHu0lrCmDCgTQ/y5Nbbis+TNjR1jjm4Q= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 h1:IAtl+7gua134xcV3NieDhJHjjOVeJhXAnYf/0hswjUY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0/go.mod h1:w+pXobnBzh95MNIkeIuAKcHe/Uu/CX2PKIvBP6ipKRA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32ay7mJG2leczfREEhoW3VfSZIvHaB+gvVo1o8DQ8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0 h1:A3/bhjP5SmELy8dcpK+uttHeh9Qrh+YnS16/VzrztRQ= -go.opentelemetry.io/otel/exporters/prometheus v0.41.0/go.mod h1:mKuXEMi9suyyNJQ99SZCO0mpWGFe0MIALtjd3r6uo7Q= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0 h1:XzjGkawtAXs20Y+s6k1GNDMBsMDOV28TOT8cxmE42qM= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.41.0/go.mod h1:HAomEgjcKZk3VJ+HHdHLnhZXeGqdzPxxNTdKYRopUXY= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes= -go.opentelemetry.io/otel/exporters/zipkin v1.18.0 h1:ZqrHgvega5NIiScTiVrtpZSpEmjUdwzkhuuCEIMAp+s= -go.opentelemetry.io/otel/exporters/zipkin v1.18.0/go.mod h1:C80yIYcSceQipAZb4Ah11EE/yERlyc1MtqJG2xP7p+s= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= -go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= -go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= -go.opentelemetry.io/otel/sdk/metric v0.41.0 h1:c3sAt9/pQ5fSIUfl0gPtClV3HhE18DCVzByD33R/zsk= -go.opentelemetry.io/otel/sdk/metric v0.41.0/go.mod h1:PmOmSt+iOklKtIg5O4Vz9H/ttcRFSNTgii+E1KGyn1w= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.45.0 h1:bldpPC7XAv7f7LKTwNfRkNdzRhjtXaWybZFFa16dAb8= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.45.0/go.mod h1:xhkNpJG3D+kmuaciNTco7cdK27Fb77J9Iqcq5CMe4Y8= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0 h1:RsQi0qJ2imFfCvZabqzM9cNXBG8k6gXMv1A0cXRmH6A= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0/go.mod h1:vsh3ySueQCiKPxFLvjWC4Z135gIa34TQ/NSqkDTZYUM= +go.opentelemetry.io/contrib/instrumentation/host v0.45.0 h1:1uzNKJDqZ6y6F5J6aKWgJjRREpKiGhBvKHlWon/bqB4= +go.opentelemetry.io/contrib/instrumentation/host v0.45.0/go.mod h1:vlqPvzDsmB4+jlERxBRXsdLCD6Q0LoBzxHqNXp3qvG4= +go.opentelemetry.io/contrib/propagators/ot v1.20.0 h1:duH7mgL6VGQH7e7QEAVOFkCQXWpCb4PjTtrhdrYrJRQ= +go.opentelemetry.io/contrib/propagators/ot v1.20.0/go.mod h1:gijQzxOq0JLj9lyZhTvqjDddGV/zaNagpPIn+2r8CEI= +go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= +go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 h1:NmnYCiR0qNufkldjVvyQfZTHSdzeHoZ41zggMsdMcLM= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0/go.mod h1:UVAO61+umUsHLtYb8KXXRoHtxUkdOPkYidzW3gipRLQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0 h1:jwV9iQdvp38fxXi8ZC+lNpxjK16MRcZlpDYvbuO1FiA= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0/go.mod h1:f3bYiqNqhoPxkvI2LrXqQVC546K7BuRDL/kKuxkujhA= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0 h1:4jJuoeOo9W6hZnz+r046fyoH5kykZPRvKfUXJVfMpB0= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0/go.mod h1:/MtYTE1SfC2QIcE0bDot6fIX+h+WvXjgTqgn9P0LNPE= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 h1:Nw7Dv4lwvGrI68+wULbcq7su9K2cebeCUrDjVrUJHxM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0/go.mod h1:1MsF6Y7gTqosgoZvHlzcaaM8DIMNZgJh87ykokoNH7Y= +go.opentelemetry.io/otel/exporters/zipkin v1.19.0 h1:EGY0h5mGliP9o/nIkVuLI0vRiQqmsYOcbwCuotksO1o= +go.opentelemetry.io/otel/exporters/zipkin v1.19.0/go.mod h1:JQgTGJP11yi3o4GHzIWYodhPisxANdqxF1eHwDSnJrI= +go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= +go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k= +go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY= +go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= +go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1236,8 +1240,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I= +google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/invalid_delivery_address_error.go b/internal/services/order_service/internal/orders/exceptions/domain_exceptions/invalid_delivery_address_error.go index b49d02ca..5ebc0d1a 100644 --- a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/invalid_delivery_address_error.go +++ b/internal/services/order_service/internal/orders/exceptions/domain_exceptions/invalid_delivery_address_error.go @@ -23,10 +23,14 @@ func NewInvalidDeliveryAddressError(message string) error { return errors.WithStackIf(br) } +func (i *invalidDeliveryAddressError) isInvalidAddress() bool { + return true +} + func IsInvalidDeliveryAddressError(err error) bool { - var ia InvalidDeliveryAddressError + var ia *invalidDeliveryAddressError if errors.As(err, &ia) { - return true + return ia.isInvalidAddress() } return false diff --git a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/invalid_email_error.go b/internal/services/order_service/internal/orders/exceptions/domain_exceptions/invalid_email_error.go index 4d8bc13c..e025a2f0 100644 --- a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/invalid_email_error.go +++ b/internal/services/order_service/internal/orders/exceptions/domain_exceptions/invalid_email_error.go @@ -24,10 +24,15 @@ func NewInvalidEmailAddressError(message string) error { return errors.WithStackIf(br) } +func (i *invalidEmailAddressError) isInvalidEmailAddressError() bool { + return true +} + func IsInvalidEmailAddressError(err error) bool { - var ie InvalidEmailAddressError + var ie *invalidEmailAddressError + if errors.As(err, &ie) { - return true + return ie.isInvalidEmailAddressError() } return false diff --git a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_domain_errors_test.go b/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_domain_errors_test.go index a81d2e5e..44735cf8 100644 --- a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_domain_errors_test.go +++ b/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_domain_errors_test.go @@ -4,6 +4,7 @@ import ( "fmt" "testing" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" "github.com/stretchr/testify/assert" @@ -22,13 +23,33 @@ func Test_Order_Not_Found_Error(t *testing.T) { } func Test_Invalid_Delivery_Address_Error(t *testing.T) { + t.Parallel() + err := NewInvalidDeliveryAddressError("address is not valid") assert.True(t, IsInvalidDeliveryAddressError(err)) fmt.Println(errorUtils.ErrorsWithStack(err)) } +func Test_Is_Not_Invalid_Delivery_Address_Error( + t *testing.T, +) { + t.Parallel() + + err := customErrors.NewBadRequestError("address is not valid") + assert.False(t, IsInvalidDeliveryAddressError(err)) +} + func Test_InvalidEmail_Address_Error(t *testing.T) { + t.Parallel() + err := NewInvalidEmailAddressError("email address is not valid") assert.True(t, IsInvalidEmailAddressError(err)) fmt.Println(errorUtils.ErrorsWithStack(err)) } + +func Test_Is_Not_InvalidEmail_Address_Error(t *testing.T) { + t.Parallel() + + err := customErrors.NewBadRequestError("email address is not valid") + assert.False(t, IsInvalidEmailAddressError(err)) +} diff --git a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_items_required_errors.go b/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_items_required_errors.go index 148b51dd..61e2647c 100644 --- a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_items_required_errors.go +++ b/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_items_required_errors.go @@ -24,10 +24,14 @@ func NewOrderShopItemsRequiredError(message string) error { return errors.WithStackIf(br) } +func (i *orderShopItemsRequiredError) isOrderShopItemsRequiredError() bool { + return true +} + func IsOrderShopItemsRequiredError(err error) bool { - var os OrderShopItemsRequiredError + var os *orderShopItemsRequiredError if errors.As(err, &os) { - return true + return os.isOrderShopItemsRequiredError() } return false diff --git a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_not_found_error.go b/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_not_found_error.go index 4346d2a1..e1993a07 100644 --- a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_not_found_error.go +++ b/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_not_found_error.go @@ -17,7 +17,9 @@ type OrderNotFoundError interface { } func NewOrderNotFoundError(id int) error { - notFound := customErrors.NewNotFoundError(fmt.Sprintf("order with id %d not found", id)) + notFound := customErrors.NewNotFoundError( + fmt.Sprintf("order with id %d not found", id), + ) customErr := customErrors.GetCustomError(notFound).(customErrors.NotFoundError) br := &orderNotFoundError{ NotFoundError: customErr, @@ -26,10 +28,14 @@ func NewOrderNotFoundError(id int) error { return errors.WithStackIf(br) } +func (i *orderNotFoundError) isorderNotFoundError() bool { + return true +} + func IsOrderNotFoundError(err error) bool { - var os OrderNotFoundError + var os *orderNotFoundError if errors.As(err, &os) { - return true + return os.isorderNotFoundError() } return false From 1bbf3753a1022d0f9bd1df2cfea484b6b0035942 Mon Sep 17 00:00:00 2001 From: mehdihadeli Date: Fri, 6 Oct 2023 16:57:49 +0330 Subject: [PATCH 04/15] feat: :sparkles: add trace and metrics pipelines for cqrs operations --- internal/pkg/core/core_fx.go | 2 - .../core/serializer/json/json_serializer.go | 121 ++++-- internal/pkg/eventstroredb/aggregate_store.go | 57 ++- internal/pkg/eventstroredb/event_store.go | 111 ++++-- internal/pkg/go.mod | 2 +- internal/pkg/go.sum | 4 +- internal/pkg/gorm_postgres/db.go | 4 +- .../gorm_generic_repository_test.go | 51 ++- internal/pkg/grpc/client.go | 4 +- internal/pkg/grpc/grpcErrors/grpc_errors.go | 9 +- .../pkg/grpc/handlers/{ => otel}/config.go | 2 +- .../pkg/grpc/handlers/{ => otel}/handler.go | 7 +- .../pkg/grpc/handlers/{ => otel}/supplier.go | 18 +- internal/pkg/grpc/otel/tracing/consts.go | 5 - internal/pkg/grpc/otel/tracing/utils.go | 41 -- internal/pkg/grpc/server.go | 4 +- .../http/custom_echo/constants/constants.go | 9 - internal/pkg/http/custom_echo/echo_server.go | 7 +- .../middlewares/otel_metrics/config.go | 8 +- .../middlewares/otel_tracing/config.go | 12 +- .../otel_tracing/tracing_middleware.go | 8 +- .../pkg/http/custom_echo/utils/tracing.go | 99 ----- .../problemDetails/problem_details.go | 9 +- .../logger/default_logger/default_logger.go | 16 +- .../pkg/logger/pipelines/logging_pipeline.go | 58 +++ internal/pkg/logger/zap/zap_logger.go | 3 +- internal/pkg/mapper/mapper.go | 45 ++- .../otel/tracing/consumer/consumer.go | 15 +- .../otel/tracing/producer/producer.go | 11 +- .../mongo_generic_repository_test.go | 69 +++- .../pkg/otel/{tracing => constants}/consts.go | 3 +- .../constants/telemetry_attributes/app/app.go | 26 ++ .../exception/exception.go | 8 + .../telemetry_attributes/general/general.go | 1 + .../telemetry_attributes/grpc/grpc.go | 3 + .../messaging/messaging.go | 14 + .../constants/telemetry_attributes/net/net.go | 11 + .../tracing/components/components.go | 8 + .../tracing/operations/operations.go | 7 + internal/pkg/otel/metrics/pipelines/config.go | 43 +++ .../metrics/pipelines/metrics_pipeline.go | 145 +++++++ internal/pkg/otel/tracing/custom_tracer.go | 4 +- internal/pkg/otel/tracing/pipelines/config.go | 43 +++ .../tracing/pipelines/tracing_pipeline.go | 109 ++++++ internal/pkg/otel/tracing/utils.go | 159 -------- internal/pkg/otel/tracing/utils/utils.go | 365 ++++++++++++++++++ .../pkg/rabbitmq/bus/rabbitmq_bus_test.go | 33 +- .../consumer/rabbitmq_consumer_test.go | 11 +- .../producer/rabbitmq_producer_test.go | 14 +- internal/pkg/rabbitmq/types/connection.go | 10 +- .../reflection/type_mappper/type_mapper.go | 45 ++- .../type_mappper/type_mapper_test.go | 6 + .../rabbitmq/rabbitmq_container_test.go | 3 +- .../eveentstoredb_container_test.go | 4 +- .../testcontainer/gorm/gorm_container_test.go | 3 +- .../mongo/mongo_container_test.go | 6 +- .../postgrespxg/postgrespgx_container_test.go | 6 +- .../rabbitmq/rabbitmq_container_test.go | 3 +- .../redis/redis_container_test.go | 4 +- internal/pkg/utils/error_utils/errors.go | 3 +- internal/services/catalog_read_service/go.mod | 2 +- internal/services/catalog_read_service/go.sum | 2 + .../repositories/mongo_product_repository.go | 15 +- .../repositories/redis_product_repository.go | 13 +- .../v1/commands/create_product_handler.go | 5 +- .../v1/commands/delete_product_handler.go | 9 +- .../v1/queries/get_product_by_id_handler.go | 9 +- .../v1/queries/get_products_handler.go | 5 +- .../v1/queries/search_products_handler.go | 5 +- .../v1/commands/update_product_handler.go | 9 +- .../infrastructure_configurator.go | 32 +- .../cmd/migration/main.go | 40 +- .../services/catalog_write_service/go.mod | 2 +- .../services/catalog_write_service/go.sum | 2 + .../repositories/pg_product_repository.go | 124 +++--- .../v1/commands/create_product.go | 27 +- .../v1/commands/create_product_handler.go | 55 +-- .../v1/dtos/create_product_response_dto.go | 10 +- .../v1/endpoints/create_product_endpoint.go | 34 +- .../v1/commands/delete_product_handler.go | 35 +- .../v1/endpoints/delete_product_endpoint.go | 32 +- .../endpoints/get_product_by_id_endpoint.go | 25 +- .../v1/queries/get_product_by_id_handler.go | 34 +- .../v1/endpoints/get_products_endpoint.go | 32 +- .../v1/queries/get_products_handler.go | 28 +- .../v1/endpoints/search_products_endpoint.go | 33 +- .../v1/queries/search_products_handler.go | 35 +- .../v1/commands/update_product_handler.go | 59 +-- .../v1/endpoints/update_product_endpoint.go | 27 +- .../infrastructure_configurator.go | 32 +- .../unit_test/unit_test_fixture.go | 3 +- internal/services/order_service/go.mod | 2 +- internal/services/order_service/go.sum | 2 + .../mongo_order_read_repository.go | 15 +- .../v1/commands/create_order_handler.go | 7 +- .../v1/queries/get_order_by_id_handler.go | 7 +- .../v1/queries/get_orders_handler.go | 5 +- .../projections/mongo_order_projection.go | 7 +- .../infrastructure_configurator.go | 32 +- .../shared/grpc/order_grpc_service_server.go | 4 +- 100 files changed, 1791 insertions(+), 976 deletions(-) rename internal/pkg/grpc/handlers/{ => otel}/config.go (99%) rename internal/pkg/grpc/handlers/{ => otel}/handler.go (98%) rename internal/pkg/grpc/handlers/{ => otel}/supplier.go (77%) delete mode 100644 internal/pkg/grpc/otel/tracing/consts.go delete mode 100644 internal/pkg/grpc/otel/tracing/utils.go delete mode 100644 internal/pkg/http/custom_echo/constants/constants.go delete mode 100644 internal/pkg/http/custom_echo/utils/tracing.go create mode 100644 internal/pkg/logger/pipelines/logging_pipeline.go rename internal/pkg/otel/{tracing => constants}/consts.go (77%) create mode 100644 internal/pkg/otel/constants/telemetry_attributes/app/app.go create mode 100644 internal/pkg/otel/constants/telemetry_attributes/exception/exception.go create mode 100644 internal/pkg/otel/constants/telemetry_attributes/general/general.go create mode 100644 internal/pkg/otel/constants/telemetry_attributes/grpc/grpc.go create mode 100644 internal/pkg/otel/constants/telemetry_attributes/messaging/messaging.go create mode 100644 internal/pkg/otel/constants/telemetry_attributes/net/net.go create mode 100644 internal/pkg/otel/constants/tracing/components/components.go create mode 100644 internal/pkg/otel/constants/tracing/operations/operations.go create mode 100644 internal/pkg/otel/metrics/pipelines/config.go create mode 100644 internal/pkg/otel/metrics/pipelines/metrics_pipeline.go create mode 100644 internal/pkg/otel/tracing/pipelines/config.go create mode 100644 internal/pkg/otel/tracing/pipelines/tracing_pipeline.go delete mode 100644 internal/pkg/otel/tracing/utils.go create mode 100644 internal/pkg/otel/tracing/utils/utils.go diff --git a/internal/pkg/core/core_fx.go b/internal/pkg/core/core_fx.go index e39f7242..e853947c 100644 --- a/internal/pkg/core/core_fx.go +++ b/internal/pkg/core/core_fx.go @@ -3,7 +3,6 @@ package core import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/json" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" "go.uber.org/fx" ) @@ -17,5 +16,4 @@ var Module = fx.Module( serializer.NewDefaultEventSerializer, serializer.NewDefaultMetadataSerializer, ), - fx.Invoke(defaultLogger.SetupDefaultLogger), ) diff --git a/internal/pkg/core/serializer/json/json_serializer.go b/internal/pkg/core/serializer/json/json_serializer.go index 7afabcb0..16018f86 100644 --- a/internal/pkg/core/serializer/json/json_serializer.go +++ b/internal/pkg/core/serializer/json/json_serializer.go @@ -19,69 +19,70 @@ func NewDefaultSerializer() serializer.Serializer { // https://www.sohamkamani.com/golang/json/#decoding-json-to-maps---unstructured-data // https://developpaper.com/mapstructure-of-go/ // https://github.com/goccy/go-json + func (s *jsonSerializer) Marshal(v interface{}) ([]byte, error) { - return json.Marshal(v) + return Marshal(v) } // Unmarshal is a wrapper around json.Unmarshal. // To unmarshal JSON into an interface value, Unmarshal stores in a map[string]interface{} func (s *jsonSerializer) Unmarshal(data []byte, v interface{}) error { - // https://pkg.go.dev/encoding/json#Unmarshal - err := json.Unmarshal(data, v) - if err != nil { - return err - } - log.Printf("deserialize structure object") - - return nil + return Unmarshal(data, v) } // UnmarshalFromJson is a wrapper around json.Unmarshal. func (s *jsonSerializer) UnmarshalFromJson(data string, v interface{}) error { - err := s.Unmarshal([]byte(data), v) - if err != nil { - return err - } - - return nil + return UnmarshalFromJSON(data, v) } // DecodeWithMapStructure is a wrapper around mapstructure.Decode. // Decode takes an input structure or map[string]interface{} and uses reflection to translate it to the output structure. output must be a pointer to a map or struct. // https://pkg.go.dev/github.com/mitchellh/mapstructure#section-readme -func (s *jsonSerializer) DecodeWithMapStructure(input interface{}, output interface{}) error { - // https://developpaper.com/mapstructure-of-go/ - return mapstructure.Decode(input, output) +func (s *jsonSerializer) DecodeWithMapStructure( + input interface{}, + output interface{}, +) error { + return DecodeWithMapStructure(input, output) } -func (s *jsonSerializer) UnmarshalToMap(data []byte, v *map[string]interface{}) error { - // https://developpaper.com/mapstructure-of-go/ - err := json.Unmarshal(data, v) - if err != nil { - return err - } - return nil +func (s *jsonSerializer) UnmarshalToMap( + data []byte, + v *map[string]interface{}, +) error { + return UnmarshalToMap(data, v) } -func (s *jsonSerializer) UnmarshalToMapFromJson(data string, v *map[string]interface{}) error { - return s.UnmarshalToMap([]byte(data), v) +func (s *jsonSerializer) UnmarshalToMapFromJson( + data string, + v *map[string]interface{}, +) error { + return UnmarshalToMapFromJson(data, v) } // PrettyPrint print input object as a formatted json string func (s *jsonSerializer) PrettyPrint(data interface{}) string { + return PrettyPrint(data) +} + +// ColoredPrettyPrint print input object as a formatted json string with color +func (s *jsonSerializer) ColoredPrettyPrint(data interface{}) string { + return ColoredPrettyPrint(data) +} + +func PrettyPrint(data interface{}) string { // https://gosamples.dev/pretty-print-json/ val, err := json.MarshalIndent(data, "", " ") if err != nil { return "" } + return string(val) } -// ColoredPrettyPrint print input object as a formatted json string with color -func (s *jsonSerializer) ColoredPrettyPrint(data interface{}) string { +func ColoredPrettyPrint(data interface{}) string { // https://github.com/TylerBrock/colorjson var obj map[string]interface{} - err := json.Unmarshal([]byte(s.PrettyPrint(data)), &obj) + err := json.Unmarshal([]byte(PrettyPrint(data)), &obj) if err != nil { return "" } @@ -92,5 +93,65 @@ func (s *jsonSerializer) ColoredPrettyPrint(data interface{}) string { if err != nil { return "" } + return string(val) } + +func Marshal(v interface{}) ([]byte, error) { + return json.Marshal(v) +} + +// Unmarshal is a wrapper around json.Unmarshal. +// To unmarshal JSON into an interface value, Unmarshal stores in a map[string]interface{} +func Unmarshal(data []byte, v interface{}) error { + // https://pkg.go.dev/encoding/json#Unmarshal + err := json.Unmarshal(data, v) + if err != nil { + return err + } + + log.Printf("deserialize structure object") + + return nil +} + +// UnmarshalFromJSON is a wrapper around json.Unmarshal. +func UnmarshalFromJSON(data string, v interface{}) error { + err := Unmarshal([]byte(data), v) + if err != nil { + return err + } + + return nil +} + +// DecodeWithMapStructure is a wrapper around mapstructure.Decode. +// Decode takes an input structure or map[string]interface{} and uses reflection to translate it to the output structure. output must be a pointer to a map or struct. +// https://pkg.go.dev/github.com/mitchellh/mapstructure#section-readme +func DecodeWithMapStructure( + input interface{}, + output interface{}, +) error { + // https://developpaper.com/mapstructure-of-go/ + return mapstructure.Decode(input, output) +} + +func UnmarshalToMap( + data []byte, + v *map[string]interface{}, +) error { + // https://developpaper.com/mapstructure-of-go/ + err := json.Unmarshal(data, v) + if err != nil { + return err + } + + return nil +} + +func UnmarshalToMapFromJson( + data string, + v *map[string]interface{}, +) error { + return UnmarshalToMap([]byte(data), v) +} diff --git a/internal/pkg/eventstroredb/aggregate_store.go b/internal/pkg/eventstroredb/aggregate_store.go index 657b7610..5b58d2a8 100644 --- a/internal/pkg/eventstroredb/aggregate_store.go +++ b/internal/pkg/eventstroredb/aggregate_store.go @@ -15,8 +15,8 @@ import ( expectedStreamVersion "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/models/stream_version" esErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/eventstroredb/errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" "emperror.dev/errors" @@ -55,7 +55,9 @@ func (a *esdbAggregateStore[T]) StoreWithVersion( ctx context.Context, ) (*appendResult.AppendEventsResult, error) { ctx, span := a.tracer.Start(ctx, "esdbAggregateStore.StoreWithVersion") - span.SetAttributes(attribute2.String("AggregateID", aggregate.Id().String())) + span.SetAttributes( + attribute2.String("AggregateID", aggregate.Id().String()), + ) defer span.End() if len(aggregate.UncommittedEvents()) == 0 { @@ -97,7 +99,7 @@ func (a *esdbAggregateStore[T]) StoreWithVersion( ctx, ) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrStatusFromSpan( span, errors.WrapIff( err, @@ -130,11 +132,18 @@ func (a *esdbAggregateStore[T]) Store( ctx, span := a.tracer.Start(ctx, "esdbAggregateStore.Store") defer span.End() - expectedVersion := expectedStreamVersion.FromInt64(aggregate.OriginalVersion()) + expectedVersion := expectedStreamVersion.FromInt64( + aggregate.OriginalVersion(), + ) - streamAppendResult, err := a.StoreWithVersion(aggregate, metadata, expectedVersion, ctx) + streamAppendResult, err := a.StoreWithVersion( + aggregate, + metadata, + expectedVersion, + ctx, + ) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrStatusFromSpan( span, errors.WrapIff( err, @@ -147,7 +156,10 @@ func (a *esdbAggregateStore[T]) Store( return streamAppendResult, nil } -func (a *esdbAggregateStore[T]) Load(ctx context.Context, aggregateId uuid.UUID) (T, error) { +func (a *esdbAggregateStore[T]) Load( + ctx context.Context, + aggregateId uuid.UUID, +) (T, error) { ctx, span := a.tracer.Start(ctx, "esdbAggregateStore.Load") defer span.End() @@ -181,7 +193,7 @@ func (a *esdbAggregateStore[T]) LoadWithReadPosition( method := reflect.ValueOf(aggregate).MethodByName("NewEmptyAggregate") if !method.IsValid() { - return *new(T), tracing.TraceErrFromSpan( + return *new(T), utils.TraceErrStatusFromSpan( span, errors.New( "[esdbAggregateStore_LoadWithReadPosition:MethodByName] aggregate does not have a `NewEmptyAggregate` method", @@ -196,7 +208,7 @@ func (a *esdbAggregateStore[T]) LoadWithReadPosition( streamEvents, err := a.getStreamEvents(streamId, position, ctx) if errors.Is(err, esdb.ErrStreamNotFound) || len(streamEvents) == 0 { - return *new(T), tracing.TraceErrFromSpan( + return *new(T), utils.TraceErrStatusFromSpan( span, errors.WithMessage( esErrors.NewAggregateNotFoundError(err, aggregateId), @@ -204,8 +216,9 @@ func (a *esdbAggregateStore[T]) LoadWithReadPosition( ), ) } + if err != nil { - return *new(T), tracing.TraceErrFromSpan( + return *new(T), utils.TraceErrStatusFromSpan( span, errors.WrapIff( err, @@ -228,20 +241,25 @@ func (a *esdbAggregateStore[T]) LoadWithReadPosition( err = aggregate.LoadFromHistory(domainEvents, meta) if err != nil { - return *new(T), tracing.TraceErrFromSpan(span, err) + return *new(T), utils.TraceStatusFromSpan(span, err) } - a.log.Infow(fmt.Sprintf("Loaded aggregate with streamId {%s} and aggregateId {%s}", - streamId.String(), - aggregateId.String()), - logger.Fields{"Aggregate": aggregate, "StreamId": streamId.String()}) + a.log.Infow( + fmt.Sprintf("Loaded aggregate with streamId {%s} and aggregateId {%s}", + streamId.String(), + aggregateId.String()), + logger.Fields{"Aggregate": aggregate, "StreamId": streamId.String()}, + ) span.SetAttributes(attribute.Object("Aggregate", aggregate)) return aggregate, nil } -func (a *esdbAggregateStore[T]) Exists(ctx context.Context, aggregateId uuid.UUID) (bool, error) { +func (a *esdbAggregateStore[T]) Exists( + ctx context.Context, + aggregateId uuid.UUID, +) (bool, error) { ctx, span := a.tracer.Start(ctx, "esdbAggregateStore.Exists") span.SetAttributes(attribute2.String("AggregateID", aggregateId.String())) defer span.End() @@ -261,7 +279,12 @@ func (a *esdbAggregateStore[T]) getStreamEvents( var streamEvents []*models.StreamEvent for true { - events, err := a.eventStore.ReadEvents(streamId, position, uint64(pageSize), ctx) + events, err := a.eventStore.ReadEvents( + streamId, + position, + uint64(pageSize), + ctx, + ) if err != nil { return nil, errors.WrapIff( err, diff --git a/internal/pkg/eventstroredb/event_store.go b/internal/pkg/eventstroredb/event_store.go index b83fd283..f2b1e57c 100644 --- a/internal/pkg/eventstroredb/event_store.go +++ b/internal/pkg/eventstroredb/event_store.go @@ -14,8 +14,8 @@ import ( expectedStreamVersion "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/models/stream_version" esErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/eventstroredb/errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "emperror.dev/errors" "github.com/EventStore/EventStore-Client-Go/esdb" @@ -39,7 +39,12 @@ func NewEventStoreDbEventStore( serializer *EsdbSerializer, tracer trace.Tracer, ) store.EventStore { - return &eventStoreDbEventStore{log: log, client: client, serializer: serializer, tracer: tracer} + return &eventStoreDbEventStore{ + log: log, + client: client, + serializer: serializer, + tracer: tracer, + } } func (e *eventStoreDbEventStore) StreamExists( @@ -59,7 +64,7 @@ func (e *eventStoreDbEventStore) StreamExists( }, 1) if err != nil { - return false, tracing.TraceErrFromSpan( + return false, utils.TraceErrStatusFromSpan( span, errors.WithMessage( esErrors.NewReadStreamError(err), @@ -104,7 +109,7 @@ func (e *eventStoreDbEventStore) AppendEvents( }, eventsData...) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrStatusFromSpan( span, errors.WithMessage( esErrors.NewAppendToStreamError(err, streamName.String()), @@ -115,11 +120,16 @@ func (e *eventStoreDbEventStore) AppendEvents( appendEventsResult = e.serializer.EsdbWriteResultToAppendEventResult(res) - span.SetAttributes(attribute.Object("AppendEventsResult", appendEventsResult)) + span.SetAttributes( + attribute.Object("AppendEventsResult", appendEventsResult), + ) e.log.Infow( "[eventStoreDbEventStore_AppendEvents] events append to stream successfully", - logger.Fields{"AppendEventsResult": appendEventsResult, "StreamId": streamName.String()}, + logger.Fields{ + "AppendEventsResult": appendEventsResult, + "StreamId": streamName.String(), + }, ) return appendEventsResult, nil @@ -141,7 +151,7 @@ func (e *eventStoreDbEventStore) AppendNewEvents( ctx, ) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrStatusFromSpan( span, errors.WithMessage( esErrors.NewAppendToStreamError(err, streamName.String()), @@ -154,7 +164,10 @@ func (e *eventStoreDbEventStore) AppendNewEvents( e.log.Infow( "[eventStoreDbEventStore_AppendNewEvents] events append to stream successfully", - logger.Fields{"AppendEventsResult": appendEventsResult, "StreamId": streamName.String()}, + logger.Fields{ + "AppendEventsResult": appendEventsResult, + "StreamId": streamName.String(), + }, ) return appendEventsResult, nil @@ -174,13 +187,15 @@ func (e *eventStoreDbEventStore) ReadEvents( ctx, streamName.String(), esdb.ReadStreamOptions{ - Direction: esdb.Forwards, - From: e.serializer.StreamReadPositionToStreamPosition(readPosition), + Direction: esdb.Forwards, + From: e.serializer.StreamReadPositionToStreamPosition( + readPosition, + ), ResolveLinkTos: true, }, count) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrStatusFromSpan( span, errors.WithMessage( esErrors.NewReadStreamError(err), @@ -191,9 +206,11 @@ func (e *eventStoreDbEventStore) ReadEvents( defer readStream.Close() - resolvedEvents, err := e.serializer.EsdbReadStreamToResolvedEvents(readStream) + resolvedEvents, err := e.serializer.EsdbReadStreamToResolvedEvents( + readStream, + ) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrStatusFromSpan( span, errors.WrapIf( err, @@ -204,7 +221,7 @@ func (e *eventStoreDbEventStore) ReadEvents( events, err := e.serializer.ResolvedEventsToStreamEvents(resolvedEvents) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrStatusFromSpan( span, errors.WrapIf( err, @@ -221,7 +238,10 @@ func (e *eventStoreDbEventStore) ReadEventsWithMaxCount( readPosition readPosition.StreamReadPosition, ctx context.Context, ) ([]*models.StreamEvent, error) { - ctx, span := e.tracer.Start(ctx, "eventStoreDbEventStore.ReadEventsWithMaxCount") + ctx, span := e.tracer.Start( + ctx, + "eventStoreDbEventStore.ReadEventsWithMaxCount", + ) span.SetAttributes(attribute2.String("StreamName", streamName.String())) defer span.End() @@ -233,7 +253,10 @@ func (e *eventStoreDbEventStore) ReadEventsFromStart( count uint64, ctx context.Context, ) ([]*models.StreamEvent, error) { - ctx, span := e.tracer.Start(ctx, "eventStoreDbEventStore.ReadEventsFromStart") + ctx, span := e.tracer.Start( + ctx, + "eventStoreDbEventStore.ReadEventsFromStart", + ) span.SetAttributes(attribute2.String("StreamName", streamName.String())) defer span.End() @@ -246,7 +269,10 @@ func (e *eventStoreDbEventStore) ReadEventsBackwards( count uint64, ctx context.Context, ) ([]*models.StreamEvent, error) { - ctx, span := e.tracer.Start(ctx, "eventStoreDbEventStore.ReadEventsBackwards") + ctx, span := e.tracer.Start( + ctx, + "eventStoreDbEventStore.ReadEventsBackwards", + ) span.SetAttributes(attribute2.String("StreamName", streamName.String())) defer span.End() @@ -254,13 +280,15 @@ func (e *eventStoreDbEventStore) ReadEventsBackwards( ctx, streamName.String(), esdb.ReadStreamOptions{ - Direction: esdb.Backwards, - From: e.serializer.StreamReadPositionToStreamPosition(readPosition), + Direction: esdb.Backwards, + From: e.serializer.StreamReadPositionToStreamPosition( + readPosition, + ), ResolveLinkTos: true, }, count) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrStatusFromSpan( span, errors.WithMessage( esErrors.NewReadStreamError(err), @@ -271,9 +299,11 @@ func (e *eventStoreDbEventStore) ReadEventsBackwards( defer readStream.Close() - resolvedEvents, err := e.serializer.EsdbReadStreamToResolvedEvents(readStream) + resolvedEvents, err := e.serializer.EsdbReadStreamToResolvedEvents( + readStream, + ) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrStatusFromSpan( span, errors.WrapIf( err, @@ -284,7 +314,7 @@ func (e *eventStoreDbEventStore) ReadEventsBackwards( events, err := e.serializer.ResolvedEventsToStreamEvents(resolvedEvents) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrStatusFromSpan( span, errors.WrapIf( err, @@ -301,11 +331,19 @@ func (e *eventStoreDbEventStore) ReadEventsBackwardsWithMaxCount( readPosition readPosition.StreamReadPosition, ctx context.Context, ) ([]*models.StreamEvent, error) { - ctx, span := e.tracer.Start(ctx, "eventStoreDbEventStore.ReadEventsBackwardsWithMaxCount") + ctx, span := e.tracer.Start( + ctx, + "eventStoreDbEventStore.ReadEventsBackwardsWithMaxCount", + ) span.SetAttributes(attribute2.String("StreamName", streamName.String())) defer span.End() - return e.ReadEventsBackwards(streamName, readPosition, uint64(math.MaxUint64), ctx) + return e.ReadEventsBackwards( + streamName, + readPosition, + uint64(math.MaxUint64), + ctx, + ) } func (e *eventStoreDbEventStore) ReadEventsBackwardsFromEnd( @@ -313,7 +351,10 @@ func (e *eventStoreDbEventStore) ReadEventsBackwardsFromEnd( count uint64, ctx context.Context, ) ([]*models.StreamEvent, error) { - ctx, span := e.tracer.Start(ctx, "eventStoreDbEventStore.ReadEventsBackwardsWithMaxCount") + ctx, span := e.tracer.Start( + ctx, + "eventStoreDbEventStore.ReadEventsBackwardsWithMaxCount", + ) span.SetAttributes(attribute2.String("StreamName", streamName.String())) defer span.End() @@ -331,7 +372,9 @@ func (e *eventStoreDbEventStore) TruncateStream( defer span.End() streamMetadata := esdb.StreamMetadata{} - streamMetadata.SetTruncateBefore(e.serializer.StreamTruncatePositionToInt64(truncatePosition)) + streamMetadata.SetTruncateBefore( + e.serializer.StreamTruncatePositionToInt64(truncatePosition), + ) writeResult, err := e.client.SetStreamMetadata( ctx, streamName.String(), @@ -342,7 +385,7 @@ func (e *eventStoreDbEventStore) TruncateStream( }, streamMetadata) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrStatusFromSpan( span, errors.WithMessage( esErrors.NewTruncateStreamError(err, streamName.String()), @@ -358,7 +401,10 @@ func (e *eventStoreDbEventStore) TruncateStream( "[eventStoreDbEventStore.TruncateStream] stream with id %s truncated successfully", streamName.String(), ), - logger.Fields{"WriteResult": writeResult, "StreamId": streamName.String()}, + logger.Fields{ + "WriteResult": writeResult, + "StreamId": streamName.String(), + }, ) return e.serializer.EsdbWriteResultToAppendEventResult(writeResult), nil @@ -382,7 +428,7 @@ func (e *eventStoreDbEventStore) DeleteStream( ), }) if err != nil { - return tracing.TraceErrFromSpan( + return utils.TraceErrStatusFromSpan( span, errors.WithMessage( esErrors.NewDeleteStreamError(err, streamName.String()), @@ -398,7 +444,10 @@ func (e *eventStoreDbEventStore) DeleteStream( "[eventStoreDbEventStore.DeleteStream] stream with id %s deleted successfully", streamName.String(), ), - logger.Fields{"DeleteResult": deleteResult, "StreamId": streamName.String()}, + logger.Fields{ + "DeleteResult": deleteResult, + "StreamId": streamName.String(), + }, ) return nil diff --git a/internal/pkg/go.mod b/internal/pkg/go.mod index c38be9da..08ad8de4 100644 --- a/internal/pkg/go.mod +++ b/internal/pkg/go.mod @@ -33,7 +33,7 @@ require ( github.com/labstack/echo/v4 v4.11.1 github.com/lib/pq v1.10.9 github.com/mcuadros/go-defaults v1.2.0 - github.com/mehdihadeli/go-mediatr v1.1.10 + github.com/mehdihadeli/go-mediatr v1.2.0 github.com/michaelklishin/rabbit-hole v1.5.0 github.com/mitchellh/mapstructure v1.5.0 github.com/nolleh/caption_json_formatter v0.2.2 diff --git a/internal/pkg/go.sum b/internal/pkg/go.sum index 5c06607e..00114664 100644 --- a/internal/pkg/go.sum +++ b/internal/pkg/go.sum @@ -464,8 +464,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mcuadros/go-defaults v1.2.0 h1:FODb8WSf0uGaY8elWJAkoLL0Ri6AlZ1bFlenk56oZtc= github.com/mcuadros/go-defaults v1.2.0/go.mod h1:WEZtHEVIGYVDqkKSWBdWKUVdRyKlMfulPaGDWIVeCWY= -github.com/mehdihadeli/go-mediatr v1.1.10 h1:NAzg4065c90lgYeb+Vzbd2WKH0tUFpxzL0mpx6hkU/A= -github.com/mehdihadeli/go-mediatr v1.1.10/go.mod h1:lwgZl7qVL/RKomObBblhG3uEte/r4nJDV95Vd+nGrMw= +github.com/mehdihadeli/go-mediatr v1.2.0 h1:XkzYF/uGfW4pwPWYAxKyY+mO6l989PbmCQWSYHuCZtU= +github.com/mehdihadeli/go-mediatr v1.2.0/go.mod h1:I9LuExxAKz6cTDJyP/SSDSmkHaPHK1/usnvEXjUY47k= github.com/michaelklishin/rabbit-hole v1.5.0 h1:Bex27BiFDsijCM9D0ezSHqyy0kehpYHuNKaPqq/a4RM= github.com/michaelklishin/rabbit-hole v1.5.0/go.mod h1:vvI1uOitYZi0O5HEGXhaWC1XT80Gy+HvFheJ+5Krlhk= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= diff --git a/internal/pkg/gorm_postgres/db.go b/internal/pkg/gorm_postgres/db.go index ab5b5328..fa85fdf3 100644 --- a/internal/pkg/gorm_postgres/db.go +++ b/internal/pkg/gorm_postgres/db.go @@ -36,7 +36,9 @@ func NewGorm(cfg *GormOptions) (*gorm.DB, error) { gormDb, err := gorm.Open( gormPostgres.Open(dataSourceName), - &gorm.Config{Logger: gromlog.NewGormCustomLogger(defaultLogger.Logger)}, + &gorm.Config{ + Logger: gromlog.NewGormCustomLogger(defaultLogger.GetLogger()), + }, ) if err != nil { return nil, err diff --git a/internal/pkg/gorm_postgres/repository/gorm_generic_repository_test.go b/internal/pkg/gorm_postgres/repository/gorm_generic_repository_test.go index 2846bb06..7b4ec5b2 100644 --- a/internal/pkg/gorm_postgres/repository/gorm_generic_repository_test.go +++ b/internal/pkg/gorm_postgres/repository/gorm_generic_repository_test.go @@ -234,7 +234,11 @@ func Test_Search(t *testing.T) { t.Fatal(err) } - models, err := repository.Search(ctx, "seed_product1", utils.NewListQuery(10, 1)) + models, err := repository.Search( + ctx, + "seed_product1", + utils.NewListQuery(10, 1), + ) if err != nil { t.Fatal(err) } @@ -247,7 +251,11 @@ func Test_Search_With_Data_Model(t *testing.T) { ctx := context.Background() repository, err := setupGenericGormRepositoryWithDataModel(ctx, t) - models, err := repository.Search(ctx, "seed_product1", utils.NewListQuery(10, 1)) + models, err := repository.Search( + ctx, + "seed_product1", + utils.NewListQuery(10, 1), + ) if err != nil { t.Fatal(err) } @@ -260,7 +268,10 @@ func Test_Where(t *testing.T) { ctx := context.Background() repository, err := setupGenericGormRepository(ctx, t) - models, err := repository.GetByFilter(ctx, map[string]interface{}{"name": "seed_product1"}) + models, err := repository.GetByFilter( + ctx, + map[string]interface{}{"name": "seed_product1"}, + ) if err != nil { t.Fatal(err) } @@ -273,7 +284,10 @@ func Test_Where_With_Data_Model(t *testing.T) { ctx := context.Background() repository, err := setupGenericGormRepositoryWithDataModel(ctx, t) - models, err := repository.GetByFilter(ctx, map[string]interface{}{"name": "seed_product1"}) + models, err := repository.GetByFilter( + ctx, + map[string]interface{}{"name": "seed_product1"}, + ) if err != nil { t.Fatal(err) } @@ -401,7 +415,10 @@ func Test_Find(t *testing.T) { entities, err := repository.Find( ctx, - specification.And(specification.Equal("is_available", true), specification.Equal("name", "seed_product1")), + specification.And( + specification.Equal("is_available", true), + specification.Equal("name", "seed_product1"), + ), ) if err != nil { return @@ -418,7 +435,10 @@ func Test_Find_With_Data_Model(t *testing.T) { entities, err := repository.Find( ctx, - specification.And(specification.Equal("is_available", true), specification.Equal("name", "seed_product1")), + specification.And( + specification.Equal("is_available", true), + specification.Equal("name", "seed_product1"), + ), ) if err != nil { return @@ -430,9 +450,8 @@ func setupGenericGormRepositoryWithDataModel( ctx context.Context, t *testing.T, ) (data.GenericRepositoryWithDataModel[*ProductGorm, *Product], error) { - defaultLogger.SetupDefaultLogger() - - db, err := gorm2.NewGormTestContainers(defaultLogger.Logger).Start(ctx, t) + db, err := gorm2.NewGormTestContainers(defaultLogger.GetLogger()). + Start(ctx, t) if err != nil { return nil, err } @@ -442,13 +461,17 @@ func setupGenericGormRepositoryWithDataModel( return nil, err } - return NewGenericGormRepositoryWithDataModel[*ProductGorm, *Product](db), nil + return NewGenericGormRepositoryWithDataModel[*ProductGorm, *Product]( + db, + ), nil } -func setupGenericGormRepository(ctx context.Context, t *testing.T) (data.GenericRepository[*ProductGorm], error) { - defaultLogger.SetupDefaultLogger() - - db, err := gorm2.NewGormTestContainers(defaultLogger.Logger).Start(ctx, t) +func setupGenericGormRepository( + ctx context.Context, + t *testing.T, +) (data.GenericRepository[*ProductGorm], error) { + db, err := gorm2.NewGormTestContainers(defaultLogger.GetLogger()). + Start(ctx, t) err = seedAndMigration(ctx, db) if err != nil { diff --git a/internal/pkg/grpc/client.go b/internal/pkg/grpc/client.go index c413be98..6557565e 100644 --- a/internal/pkg/grpc/client.go +++ b/internal/pkg/grpc/client.go @@ -5,7 +5,7 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/handlers" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/handlers/otel" "emperror.dev/errors" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" @@ -34,7 +34,7 @@ func NewGrpcClient(config *config.GrpcOptions) (GrpcClient, error) { // https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/example/client/main.go#L47C3-L47C52 // https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/doc.go grpc.WithStatsHandler(otelgrpc.NewClientHandler()), - grpc.WithStatsHandler(handlers.NewClientHandler()), + grpc.WithStatsHandler(otel.NewClientHandler()), ) if err != nil { return nil, err diff --git a/internal/pkg/grpc/grpcErrors/grpc_errors.go b/internal/pkg/grpc/grpcErrors/grpc_errors.go index e2fe7427..13424bc7 100644 --- a/internal/pkg/grpc/grpcErrors/grpc_errors.go +++ b/internal/pkg/grpc/grpcErrors/grpc_errors.go @@ -34,7 +34,12 @@ type GrpcErr interface { ToGrpcResponseErr() error } -func NewGrpcError(status codes.Code, title string, detail string, stackTrace string) GrpcErr { +func NewGrpcError( + status codes.Code, + title string, + detail string, + stackTrace string, +) GrpcErr { grpcErr := &grpcErr{ Status: status, Title: title, @@ -107,7 +112,7 @@ func (p *grpcErr) ToGrpcResponseErr() error { } func (p *grpcErr) ToJson() string { - defaultLogger.Logger.Error(p.Error()) + defaultLogger.GetLogger().Error(p.Error()) stackTrace := p.GetStackTrace() fmt.Println(stackTrace) diff --git a/internal/pkg/grpc/handlers/config.go b/internal/pkg/grpc/handlers/otel/config.go similarity index 99% rename from internal/pkg/grpc/handlers/config.go rename to internal/pkg/grpc/handlers/otel/config.go index aba9c85e..070d15eb 100644 --- a/internal/pkg/grpc/handlers/config.go +++ b/internal/pkg/grpc/handlers/otel/config.go @@ -1,4 +1,4 @@ -package handlers +package otel import ( "go.opentelemetry.io/otel" diff --git a/internal/pkg/grpc/handlers/handler.go b/internal/pkg/grpc/handlers/otel/handler.go similarity index 98% rename from internal/pkg/grpc/handlers/handler.go rename to internal/pkg/grpc/handlers/otel/handler.go index 09e2672f..caded99c 100644 --- a/internal/pkg/grpc/handlers/handler.go +++ b/internal/pkg/grpc/handlers/otel/handler.go @@ -1,4 +1,4 @@ -package handlers +package otel import ( "context" @@ -177,7 +177,10 @@ func (h *handler) tagRPC( gctx := gRPCContext{attributes: attributes, startTime: time.Now()} - return context.WithValue(ctx, gRPCContextKey{}, &gctx) + return inject( + context.WithValue(ctx, gRPCContextKey{}, &gctx), + h.config.propagator, + ) } func (h *handler) handleRPC(ctx context.Context, rs stats.RPCStats) { diff --git a/internal/pkg/grpc/handlers/supplier.go b/internal/pkg/grpc/handlers/otel/supplier.go similarity index 77% rename from internal/pkg/grpc/handlers/supplier.go rename to internal/pkg/grpc/handlers/otel/supplier.go index 4751ca09..1a9b996d 100644 --- a/internal/pkg/grpc/handlers/supplier.go +++ b/internal/pkg/grpc/handlers/otel/supplier.go @@ -1,4 +1,4 @@ -package handlers +package otel import ( "context" @@ -51,3 +51,19 @@ func extract( metadata: &md, }) } + +func inject( + ctx context.Context, + propagators propagation.TextMapPropagator, +) context.Context { + md, ok := metadata.FromOutgoingContext(ctx) + if !ok { + md = metadata.MD{} + } + + propagators.Inject(ctx, &metadataSupplier{ + metadata: &md, + }) + + return metadata.NewOutgoingContext(ctx, md) +} diff --git a/internal/pkg/grpc/otel/tracing/consts.go b/internal/pkg/grpc/otel/tracing/consts.go deleted file mode 100644 index bb93bc15..00000000 --- a/internal/pkg/grpc/otel/tracing/consts.go +++ /dev/null @@ -1,5 +0,0 @@ -package tracing - -const ( - GrpcErrorMessage = "rpc.grpc.error_message" -) diff --git a/internal/pkg/grpc/otel/tracing/utils.go b/internal/pkg/grpc/otel/tracing/utils.go deleted file mode 100644 index c9dc8b0e..00000000 --- a/internal/pkg/grpc/otel/tracing/utils.go +++ /dev/null @@ -1,41 +0,0 @@ -package tracing - -import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/grpcErrors" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/codes" - semconv "go.opentelemetry.io/otel/semconv/v1.21.0" - "go.opentelemetry.io/otel/trace" -) - -// TraceGrpcErrFromSpan setting span with status error with error message -func TraceGrpcErrFromSpan(span trace.Span, err error) error { - if err != nil { - stackTraceError := errorUtils.ErrorsWithStack(err) - span.SetStatus(codes.Error, "") - span.SetAttributes(attribute.String(GrpcErrorMessage, stackTraceError)) - if customErrors.IsCustomError(err) { - grpcErr := grpcErrors.ParseError(err) - span.SetAttributes(semconv.RPCGRPCStatusCodeKey.Int(int(grpcErr.GetStatus()))) - } - span.RecordError(err) - } - - return err -} - -// TraceGrpcErrFromSpanWithCode setting span with status error with error message -func TraceGrpcErrFromSpanWithCode(span trace.Span, err error, code int) error { - if err != nil { - stackTraceError := errorUtils.ErrorsWithStack(err) - span.SetStatus(codes.Error, "") - span.SetAttributes(semconv.RPCGRPCStatusCodeKey.Int(code)) - span.SetAttributes(attribute.String(GrpcErrorMessage, stackTraceError)) - span.RecordError(err) - } - - return err -} diff --git a/internal/pkg/grpc/server.go b/internal/pkg/grpc/server.go index 7285a0ea..98c0cce3 100644 --- a/internal/pkg/grpc/server.go +++ b/internal/pkg/grpc/server.go @@ -6,7 +6,7 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/handlers" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/handlers/otel" grpcError "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/interceptors/grpc_error" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" @@ -63,7 +63,7 @@ func NewGrpcServer( // https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/doc.go // https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/instrumentation/google.golang.org/grpc/otelgrpc/example/server/main.go#L143C3-L143C50 googleGrpc.StatsHandler(otelgrpc.NewServerHandler()), - googleGrpc.StatsHandler(handlers.NewServerHandler()), + googleGrpc.StatsHandler(otel.NewServerHandler()), googleGrpc.KeepaliveParams(keepalive.ServerParameters{ MaxConnectionIdle: maxConnectionIdle * time.Minute, diff --git a/internal/pkg/http/custom_echo/constants/constants.go b/internal/pkg/http/custom_echo/constants/constants.go deleted file mode 100644 index 1a04bab6..00000000 --- a/internal/pkg/http/custom_echo/constants/constants.go +++ /dev/null @@ -1,9 +0,0 @@ -package constants - -type otel struct { - HttpErrorMessage string -} - -var Otel = otel{ - HttpErrorMessage: "http.error_message", -} diff --git a/internal/pkg/http/custom_echo/echo_server.go b/internal/pkg/http/custom_echo/echo_server.go index 5f34bef7..741df138 100644 --- a/internal/pkg/http/custom_echo/echo_server.go +++ b/internal/pkg/http/custom_echo/echo_server.go @@ -123,11 +123,14 @@ func (s *echoHttpServer) SetupDefaultMiddlewares() { ), ) s.echo.Use( - oteltracing.HttpTrace(s.config.Name, oteltracing.WithSkipper(skipper)), + oteltracing.HttpTrace( + oteltracing.WithSkipper(skipper), + oteltracing.WithServiceName(s.config.Name), + ), ) s.echo.Use( otelMetrics.HTTPMetrics( - otelMetrics.SetServiceName(s.config.Name), + otelMetrics.WithServiceName(s.config.Name), otelMetrics.WithSkipper(skipper)), ) s.echo.Use(middleware.BodyLimit(constants.BodyLimit)) diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/config.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/config.go index cf386453..52bb3009 100644 --- a/internal/pkg/http/custom_echo/middlewares/otel_metrics/config.go +++ b/internal/pkg/http/custom_echo/middlewares/otel_metrics/config.go @@ -47,10 +47,10 @@ func (o optionFunc) apply(c *config) { o(c) } -// SetNamespace will set the metrics namespace that will be added to all metric configurations. It will be a prefix to each +// WithNamespace will set the metrics namespace that will be added to all metric configurations. It will be a prefix to each // metric name. For example, if namespace is "myapp", then requests_total metric will be myapp_http_requests_total // (after namespace there is also the subsystem prefix, "http" in this case). -func SetNamespace(v string) Option { +func WithNamespace(v string) Option { return optionFunc(func(cfg *config) { if cfg.namespace != "" { cfg.namespace = v @@ -58,7 +58,7 @@ func SetNamespace(v string) Option { }) } -func SetServiceName(v string) Option { +func WithServiceName(v string) Option { return optionFunc(func(cfg *config) { if cfg.serviceName != "" { cfg.serviceName = v @@ -66,7 +66,7 @@ func SetServiceName(v string) Option { }) } -func SetInstrumentationName(v string) Option { +func WithInstrumentationName(v string) Option { return optionFunc(func(cfg *config) { if cfg.instrumentationName != "" { cfg.instrumentationName = v diff --git a/internal/pkg/http/custom_echo/middlewares/otel_tracing/config.go b/internal/pkg/http/custom_echo/middlewares/otel_tracing/config.go index 2f265374..e01d1641 100644 --- a/internal/pkg/http/custom_echo/middlewares/otel_tracing/config.go +++ b/internal/pkg/http/custom_echo/middlewares/otel_tracing/config.go @@ -15,6 +15,7 @@ type config struct { propagators propagation.TextMapPropagator skipper middleware.Skipper instrumentationName string + serviceName string } // Option specifies instrumentation configuration options. @@ -33,6 +34,7 @@ var defualtConfig = config{ propagators: otel.GetTextMapPropagator(), skipper: middleware.DefaultSkipper, instrumentationName: "echo", + serviceName: "app", } // WithPropagators specifies propagators to use for extracting @@ -63,10 +65,18 @@ func WithSkipper(skipper middleware.Skipper) Option { }) } -func SetInstrumentationName(v string) Option { +func WithInstrumentationName(v string) Option { return optionFunc(func(cfg *config) { if cfg.instrumentationName != "" { cfg.instrumentationName = v } }) } + +func WithServiceName(v string) Option { + return optionFunc(func(cfg *config) { + if cfg.serviceName != "" { + cfg.serviceName = v + } + }) +} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_tracing/tracing_middleware.go b/internal/pkg/http/custom_echo/middlewares/otel_tracing/tracing_middleware.go index 877e26ce..f5c58591 100644 --- a/internal/pkg/http/custom_echo/middlewares/otel_tracing/tracing_middleware.go +++ b/internal/pkg/http/custom_echo/middlewares/otel_tracing/tracing_middleware.go @@ -8,7 +8,7 @@ package oteltracing import ( "fmt" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/utils" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/labstack/echo/v4" "go.opentelemetry.io/otel/propagation" @@ -18,7 +18,7 @@ import ( ) // HttpTrace returns echo middleware which will trace incoming requests. -func HttpTrace(service string, opts ...Option) echo.MiddlewareFunc { +func HttpTrace(opts ...Option) echo.MiddlewareFunc { cfg := defualtConfig for _, opt := range opts { opt.apply(&cfg) @@ -54,7 +54,7 @@ func HttpTrace(service string, opts ...Option) echo.MiddlewareFunc { // https://github.com/open-telemetry/opentelemetry-go/pull/4362 opts := []oteltrace.SpanStartOption{ oteltrace.WithAttributes( - httpconv.ServerRequest(service, request)...), + httpconv.ServerRequest(cfg.serviceName, request)...), oteltrace.WithSpanKind(oteltrace.SpanKindServer), } @@ -88,7 +88,7 @@ func HttpTrace(service string, opts ...Option) echo.MiddlewareFunc { } status := c.Response().Status - err = utils.HttpTraceFromSpanWithCode(span, err, status) + err = utils.HttpTraceStatusFromSpanWithCode(span, err, status) return err } diff --git a/internal/pkg/http/custom_echo/utils/tracing.go b/internal/pkg/http/custom_echo/utils/tracing.go deleted file mode 100644 index 342c357e..00000000 --- a/internal/pkg/http/custom_echo/utils/tracing.go +++ /dev/null @@ -1,99 +0,0 @@ -package utils - -import ( - "context" - "net/http" - - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/constants" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/problemDetails" - errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/codes" - "go.opentelemetry.io/otel/semconv/v1.20.0/httpconv" - semconv "go.opentelemetry.io/otel/semconv/v1.21.0" - "go.opentelemetry.io/otel/trace" -) - -// HttpTraceFromSpan create an error span if we have an error and a successful span when error is nil -func HttpTraceFromSpan(span trace.Span, err error) error { - isError := err != nil - - if customErrors.IsCustomError(err) { - httpError := problemDetails.ParseError(err) - - return HttpTraceFromSpanWithCode( - span, - err, - httpError.GetStatus(), - ) - } - - var ( - status int - code codes.Code - ) - - if isError { - status = http.StatusInternalServerError - code = codes.Error - } else { - status = http.StatusOK - code = codes.Ok - } - - span.SetStatus(code, "") - span.SetAttributes( - semconv.HTTPStatusCode(status), - ) - - if isError { - stackTraceError := errorUtils.ErrorsWithStack(err) - - // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors - span.SetAttributes( - attribute.String(constants.Otel.HttpErrorMessage, stackTraceError), - ) - span.RecordError(err) - } - - return err -} - -// HttpTraceFromSpanWithCode create an error span with specific status code if we have an error and a successful span when error is nil with a specific status -func HttpTraceFromSpanWithCode(span trace.Span, err error, code int) error { - if err != nil { - stackTraceError := errorUtils.ErrorsWithStack(err) - - // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors - span.SetAttributes( - attribute.String(constants.Otel.HttpErrorMessage, stackTraceError), - ) - span.RecordError(err) - } - - if code > 0 { - // httpconv doesn't exist in semconv v1.21.0, and it moved to `opentelemetry-go-contrib` pkg - // https://github.com/open-telemetry/opentelemetry-go/pull/4362 - // https://github.com/open-telemetry/opentelemetry-go/issues/4081 - // using ClientStatus instead of ServerStatus for consideration of 4xx status as error - span.SetStatus(httpconv.ClientStatus(code)) - span.SetAttributes(semconv.HTTPStatusCode(code)) - } else { - span.SetStatus(codes.Error, "") - span.SetAttributes(semconv.HTTPStatusCode(http.StatusInternalServerError)) - } - - return err -} - -// HttpTraceFromContext create an error span if we have an error and a successful span when error is nil -func HttpTraceFromContext(ctx context.Context, err error) error { - // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors - span := trace.SpanFromContext(ctx) - - defer span.End() - - return HttpTraceFromSpan(span, err) -} diff --git a/internal/pkg/http/http_errors/problemDetails/problem_details.go b/internal/pkg/http/http_errors/problemDetails/problem_details.go index f7a8d61f..aa85b40c 100644 --- a/internal/pkg/http/http_errors/problemDetails/problem_details.go +++ b/internal/pkg/http/http_errors/problemDetails/problem_details.go @@ -114,7 +114,12 @@ func (p *problemDetail) SetStackTrace(stackTrace string) ProblemDetailErr { } // NewProblemDetail New ProblemDetail Error -func NewProblemDetail(status int, title string, detail string, stackTrace string) ProblemDetailErr { +func NewProblemDetail( + status int, + title string, + detail string, + stackTrace string, +) ProblemDetailErr { problemDetail := &problemDetail{ Status: status, Title: title, @@ -191,7 +196,7 @@ func ResolveProblemDetail(err error) ProblemDetailErr { // WriteTo writes the JSON Problem to an HTTP Response Writer func WriteTo(p ProblemDetailErr, w http.ResponseWriter) (int, error) { - defaultLogger.Logger.Error(p.Error()) + defaultLogger.GetLogger().Error(p.Error()) stackTrace := p.GetStackTrace() fmt.Println(stackTrace) diff --git a/internal/pkg/logger/default_logger/default_logger.go b/internal/pkg/logger/default_logger/default_logger.go index 0623b17c..e7634d0e 100644 --- a/internal/pkg/logger/default_logger/default_logger.go +++ b/internal/pkg/logger/default_logger/default_logger.go @@ -11,20 +11,20 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" ) -var Logger logger.Logger +var l logger.Logger -func SetupDefaultLogger() { +func initLogger() { logType := os.Getenv("LogConfig_LogType") switch logType { case "Zap", "": - Logger = zap.NewZapLogger( + l = zap.NewZapLogger( &config.LogOptions{LogType: models.Zap, CallerEnabled: false}, constants.Dev, ) break case "Logrus": - Logger = logrous.NewLogrusLogger( + l = logrous.NewLogrusLogger( &config.LogOptions{LogType: models.Logrus, CallerEnabled: false}, constants.Dev, ) @@ -32,3 +32,11 @@ func SetupDefaultLogger() { default: } } + +func GetLogger() logger.Logger { + if l == nil { + initLogger() + } + + return l +} diff --git a/internal/pkg/logger/pipelines/logging_pipeline.go b/internal/pkg/logger/pipelines/logging_pipeline.go new file mode 100644 index 00000000..ca8889b7 --- /dev/null +++ b/internal/pkg/logger/pipelines/logging_pipeline.go @@ -0,0 +1,58 @@ +package pipelines + +import ( + "context" + "fmt" + "time" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + + "github.com/mehdihadeli/go-mediatr" +) + +type requestLoggerPipeline struct { + logger logger.Logger +} + +func NewLoggingPipeline(l logger.Logger) mediatr.PipelineBehavior { + return &requestLoggerPipeline{logger: l} +} + +func (r *requestLoggerPipeline) Handle( + ctx context.Context, + request interface{}, + next mediatr.RequestHandlerFunc, +) (interface{}, error) { + startTime := time.Now() + defer func() { + elapsed := time.Since(startTime) + r.logger.Infof("Request took %s", elapsed) + }() + + requestName := typeMapper.GetNonePointerTypeName(request) + + r.logger.Infow( + fmt.Sprintf("Handling request: '%s'", requestName), + logger.Fields{"Request": request}, + ) + + response, err := next(ctx) + if err != nil { + r.logger.Infof("Request failed with error: %v", err) + + return nil, err + } + + responseName := typeMapper.GetNonePointerTypeName(response) + + r.logger.Infow( + fmt.Sprintf( + "Request handled successfully with response: '%s'", + responseName, + ), + logger.Fields{"Response": response}, + ) + + return response, nil +} diff --git a/internal/pkg/logger/zap/zap_logger.go b/internal/pkg/logger/zap/zap_logger.go index a0ac80fd..6407c960 100644 --- a/internal/pkg/logger/zap/zap_logger.go +++ b/internal/pkg/logger/zap/zap_logger.go @@ -312,6 +312,7 @@ func getFieldType(value interface{}) zapcore.FieldType { case error: return zapcore.ErrorType default: - return zapcore.StringerType + // uses reflection to serialize arbitrary objects, so it can be slow and allocation-heavy. + return zapcore.ReflectType } } diff --git a/internal/pkg/mapper/mapper.go b/internal/pkg/mapper/mapper.go index e5693696..4adb891e 100644 --- a/internal/pkg/mapper/mapper.go +++ b/internal/pkg/mapper/mapper.go @@ -80,9 +80,16 @@ func CreateMap[TSrc any, TDst any]() error { return ErrUnsupportedMap } - if srcType.Kind() == reflect.Ptr && srcType.Elem().Kind() == reflect.Struct { - pointerStructTypeKey := mappingsEntry{SourceType: srcType, DestinationType: desType} - nonePointerStructTypeKey := mappingsEntry{SourceType: srcType.Elem(), DestinationType: desType.Elem()} + if srcType.Kind() == reflect.Ptr && + srcType.Elem().Kind() == reflect.Struct { + pointerStructTypeKey := mappingsEntry{ + SourceType: srcType, + DestinationType: desType, + } + nonePointerStructTypeKey := mappingsEntry{ + SourceType: srcType.Elem(), + DestinationType: desType.Elem(), + } if _, ok := maps[nonePointerStructTypeKey]; ok { return ErrMapAlreadyExists } @@ -108,11 +115,13 @@ func CreateMap[TSrc any, TDst any]() error { maps[pointerStructTypeKey] = nil } - if srcType.Kind() == reflect.Ptr && srcType.Elem().Kind() == reflect.Struct { + if srcType.Kind() == reflect.Ptr && + srcType.Elem().Kind() == reflect.Struct { srcType = srcType.Elem() } - if desType.Kind() == reflect.Ptr && desType.Elem().Kind() == reflect.Struct { + if desType.Kind() == reflect.Ptr && + desType.Elem().Kind() == reflect.Struct { desType = desType.Elem() } @@ -163,14 +172,16 @@ func Map[TDes any, TSrc any](src TSrc) (TDes, error) { desIsArray := false srcIsArray := false - if srcType.Kind() == reflect.Array || (srcType.Kind() == reflect.Ptr && srcType.Elem().Kind() == reflect.Array) || + if srcType.Kind() == reflect.Array || + (srcType.Kind() == reflect.Ptr && srcType.Elem().Kind() == reflect.Array) || srcType.Kind() == reflect.Slice || (srcType.Kind() == reflect.Ptr && srcType.Elem().Kind() == reflect.Slice) { srcType = srcType.Elem() srcIsArray = true } - if desType.Kind() == reflect.Array || (desType.Kind() == reflect.Ptr && desType.Elem().Kind() == reflect.Array) || + if desType.Kind() == reflect.Array || + (desType.Kind() == reflect.Ptr && desType.Elem().Kind() == reflect.Array) || desType.Kind() == reflect.Slice || (desType.Kind() == reflect.Ptr && desType.Elem().Kind() == reflect.Slice) { desType = desType.Elem() @@ -209,7 +220,7 @@ func configProfile(srcType reflect.Type, destType reflect.Type) { // check for provided types kind. // if not struct - skip. if srcType.Kind() != reflect.Struct { - defaultLogger.Logger.Errorf( + defaultLogger.GetLogger().Errorf( "expected reflect.Struct kind for type %s, but got %s", srcType.String(), srcType.Kind().String(), @@ -217,7 +228,7 @@ func configProfile(srcType reflect.Type, destType reflect.Type) { } if destType.Kind() != reflect.Struct { - defaultLogger.Logger.Errorf( + defaultLogger.GetLogger().Errorf( "expected reflect.Struct kind for type %s, but got %s", destType.String(), destType.Kind().String(), @@ -234,7 +245,10 @@ func configProfile(srcType reflect.Type, destType reflect.Type) { for srcKey, srcTag := range srcMeta.keysToTags { if _, ok := destMeta.keysToTags[strcase.ToCamel(srcKey)]; ok { - profile = append(profile, [2]string{srcKey, strcase.ToCamel(srcKey)}) + profile = append( + profile, + [2]string{srcKey, strcase.ToCamel(srcKey)}, + ) } // case src key equals dest key @@ -319,7 +333,7 @@ func mapStructs[TDes any, TSrc any](src reflect.Value, dest reflect.Value) { // if types or their slices were not registered - abort profile, ok := profiles[getProfileKey(src.Type(), dest.Type())] if !ok { - defaultLogger.Logger.Errorf( + defaultLogger.GetLogger().Errorf( "no conversion specified for types %s and %s", src.Type().String(), dest.Type().String(), @@ -337,7 +351,9 @@ func mapStructs[TDes any, TSrc any](src reflect.Value, dest reflect.Value) { // var destinationFieldValue reflect.Value if !sourceField.CanInterface() { if mapperConfig.MapUnexportedFields { - sourceFiledValue = reflectionHelper.GetFieldValue(sourceField) + sourceFiledValue = reflectionHelper.GetFieldValue( + sourceField, + ) } else { // for getting pointer for non-pointer struct we can use reflect.Addr() for calling pointer receivers properties sourceFiledValue = reflectionHelper.GetFieldValueFromMethodAndReflectValue(src.Addr(), strcase.ToCamel(keys[SrcKeyIndex])) @@ -404,7 +420,10 @@ func mapMaps[TDes any, TSrc any](src reflect.Value, dest reflect.Value) { } } -func processValues[TDes any, TSrc any](src reflect.Value, dest reflect.Value) error { +func processValues[TDes any, TSrc any]( + src reflect.Value, + dest reflect.Value, +) error { // if src of dest is an interface - get underlying type if src.Kind() == reflect.Interface { src = src.Elem() diff --git a/internal/pkg/messaging/otel/tracing/consumer/consumer.go b/internal/pkg/messaging/otel/tracing/consumer/consumer.go index 250faf88..f3a573da 100644 --- a/internal/pkg/messaging/otel/tracing/consumer/consumer.go +++ b/internal/pkg/messaging/otel/tracing/consumer/consumer.go @@ -8,8 +8,9 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" messageHeader "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/message_header" messageTracing "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants" tracingHeaders "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/tracing_headers" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" @@ -57,7 +58,7 @@ func StartConsumerSpan( } func FinishConsumerSpan(span trace.Span, err error) error { - messageName := tracing.GetSpanAttribute(span, messageTracing.MessageName).Value.AsString() + messageName := utils.GetSpanAttribute(span, messageTracing.MessageName).Value.AsString() if err != nil { span.AddEvent(fmt.Sprintf("failed to consume message '%s' from the broker", messageName)) @@ -65,7 +66,7 @@ func FinishConsumerSpan(span trace.Span, err error) error { } span.SetAttributes( - attribute.Key(tracing.SpanId).String(span.SpanContext().SpanID().String()), // current span id + attribute.Key(constants.SpanId).String(span.SpanContext().SpanID().String()), // current span id ) span.AddEvent(fmt.Sprintf("message '%s' consumed from the broker succesfully", messageName)) @@ -87,10 +88,10 @@ func getTraceOptions( semconv.MessageIDKey.String(messageHeader.GetMessageId(*meta)), semconv.MessagingMessageConversationID(correlationId), semconv.MessagingOperationReceive, - attribute.Key(tracing.TraceId).String(tracingHeaders.GetTracingTraceId(*meta)), - attribute.Key(tracing.Traceparent).String(tracingHeaders.GetTracingTraceparent(*meta)), - attribute.Key(tracing.ParentSpanId).String(tracingHeaders.GetTracingParentSpanId(*meta)), - attribute.Key(tracing.Timestamp).Int64(time.Now().UnixMilli()), + attribute.Key(constants.TraceId).String(tracingHeaders.GetTracingTraceId(*meta)), + attribute.Key(constants.Traceparent).String(tracingHeaders.GetTracingTraceparent(*meta)), + attribute.Key(constants.ParentSpanId).String(tracingHeaders.GetTracingParentSpanId(*meta)), + attribute.Key(constants.Timestamp).Int64(time.Now().UnixMilli()), attribute.Key(messageTracing.MessageType).String(messageHeader.GetMessageType(*meta)), attribute.Key(messageTracing.MessageName).String(messageHeader.GetMessageName(*meta)), attribute.Key(messageTracing.Payload).String(payload), diff --git a/internal/pkg/messaging/otel/tracing/producer/producer.go b/internal/pkg/messaging/otel/tracing/producer/producer.go index 381a7cba..1533dc08 100644 --- a/internal/pkg/messaging/otel/tracing/producer/producer.go +++ b/internal/pkg/messaging/otel/tracing/producer/producer.go @@ -9,7 +9,8 @@ import ( messageHeader "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/message_header" messageTracing "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" @@ -59,15 +60,15 @@ func StartProducerSpan( } func FinishProducerSpan(span trace.Span, err error) error { - messageName := tracing.GetSpanAttribute(span, messageTracing.MessageName).Value.AsString() + messageName := utils.GetSpanAttribute(span, messageTracing.MessageName).Value.AsString() if err != nil { span.AddEvent(fmt.Sprintf("failed to publsih message '%s' to the broker", messageName)) _ = messageTracing.TraceMessagingErrFromSpan(span, err) } span.SetAttributes( - attribute.Key(tracing.TraceId).String(span.SpanContext().TraceID().String()), - attribute.Key(tracing.SpanId).String(span.SpanContext().SpanID().String()), // current span id + attribute.Key(constants.TraceId).String(span.SpanContext().TraceID().String()), + attribute.Key(constants.SpanId).String(span.SpanContext().SpanID().String()), // current span id ) span.AddEvent(fmt.Sprintf("message '%s' published to the broker succesfully", messageName)) @@ -93,7 +94,7 @@ func getTraceOptions( attribute.Key(messageTracing.MessageName).String(messageHeader.GetMessageName(*meta)), attribute.Key(messageTracing.Payload).String(payload), attribute.String(messageTracing.Headers, meta.ToJson()), - attribute.Key(tracing.Timestamp).Int64(time.Now().UnixMilli()), + attribute.Key(constants.Timestamp).Int64(time.Now().UnixMilli()), semconv.MessagingDestinationName(producerTracingOptions.Destination), semconv.MessagingSystemKey.String(producerTracingOptions.MessagingSystem), semconv.MessagingOperationKey.String("send"), diff --git a/internal/pkg/mongodb/repository/mongo_generic_repository_test.go b/internal/pkg/mongodb/repository/mongo_generic_repository_test.go index 7837d708..d36a8cd0 100644 --- a/internal/pkg/mongodb/repository/mongo_generic_repository_test.go +++ b/internal/pkg/mongodb/repository/mongo_generic_repository_test.go @@ -230,7 +230,10 @@ func Test_First_Or_Default(t *testing.T) { } p := all.Items[0] - single, err := repository.FirstOrDefault(ctx, map[string]interface{}{"_id": p.ID}) + single, err := repository.FirstOrDefault( + ctx, + map[string]interface{}{"_id": p.ID}, + ) if err != nil { t.Fatal(err) } @@ -250,7 +253,10 @@ func Test_First_Or_Default_With_Data_Model(t *testing.T) { } p := all.Items[0] - single, err := repository.FirstOrDefault(ctx, map[string]interface{}{"_id": p.ID}) + single, err := repository.FirstOrDefault( + ctx, + map[string]interface{}{"_id": p.ID}, + ) if err != nil { t.Fatal(err) } @@ -294,7 +300,11 @@ func Test_Search(t *testing.T) { t.Fatal(err) } - models, err := repository.Search(ctx, "seed_product1", utils.NewListQuery(10, 1)) + models, err := repository.Search( + ctx, + "seed_product1", + utils.NewListQuery(10, 1), + ) if err != nil { t.Fatal(err) } @@ -307,7 +317,11 @@ func Test_Search_With_Data_Model(t *testing.T) { ctx := context.Background() repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) - models, err := repository.Search(ctx, "seed_product1", utils.NewListQuery(10, 1)) + models, err := repository.Search( + ctx, + "seed_product1", + utils.NewListQuery(10, 1), + ) if err != nil { t.Fatal(err) } @@ -320,7 +334,10 @@ func Test_GetByFilter(t *testing.T) { ctx := context.Background() repository, err := setupGenericMongoRepository(ctx, t) - models, err := repository.GetByFilter(ctx, map[string]interface{}{"name": "seed_product1"}) + models, err := repository.GetByFilter( + ctx, + map[string]interface{}{"name": "seed_product1"}, + ) if err != nil { t.Fatal(err) } @@ -333,7 +350,10 @@ func Test_GetByFilter_With_Data_Model(t *testing.T) { ctx := context.Background() repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) - models, err := repository.GetByFilter(ctx, map[string]interface{}{"name": "seed_product1"}) + models, err := repository.GetByFilter( + ctx, + map[string]interface{}{"name": "seed_product1"}, + ) if err != nil { t.Fatal(err) } @@ -509,7 +529,10 @@ func Test_Find(t *testing.T) { entities, err := repository.Find( ctx, - specification.And(specification.Equal("is_available", true), specification.Equal("name", "seed_product1")), + specification.And( + specification.Equal("is_available", true), + specification.Equal("name", "seed_product1"), + ), ) if err != nil { return @@ -526,7 +549,10 @@ func Test_Find_With_Data_Model(t *testing.T) { entities, err := repository.Find( ctx, - specification.And(specification.Equal("is_available", true), specification.Equal("name", "seed_product1")), + specification.And( + specification.Equal("is_available", true), + specification.Equal("name", "seed_product1"), + ), ) if err != nil { return @@ -538,9 +564,8 @@ func setupGenericMongoRepositoryWithDataModel( ctx context.Context, t *testing.T, ) (data.GenericRepositoryWithDataModel[*ProductMongo, *Product], error) { - defaultLogger.SetupDefaultLogger() - - db, err := mongo2.NewMongoTestContainers(defaultLogger.Logger).Start(ctx, t) + db, err := mongo2.NewMongoTestContainers(defaultLogger.GetLogger()). + Start(ctx, t) if err != nil { return nil, err } @@ -550,13 +575,19 @@ func setupGenericMongoRepositoryWithDataModel( return nil, err } - return NewGenericMongoRepositoryWithDataModel[*ProductMongo, *Product](db, DatabaseName, CollectionName), nil + return NewGenericMongoRepositoryWithDataModel[*ProductMongo, *Product]( + db, + DatabaseName, + CollectionName, + ), nil } -func setupGenericMongoRepository(ctx context.Context, t *testing.T) (data.GenericRepository[*ProductMongo], error) { - defaultLogger.SetupDefaultLogger() - - db, err := mongo2.NewMongoTestContainers(defaultLogger.Logger).Start(ctx, t) +func setupGenericMongoRepository( + ctx context.Context, + t *testing.T, +) (data.GenericRepository[*ProductMongo], error) { + db, err := mongo2.NewMongoTestContainers(defaultLogger.GetLogger()). + Start(ctx, t) if err != nil { return nil, err } @@ -566,7 +597,11 @@ func setupGenericMongoRepository(ctx context.Context, t *testing.T) (data.Generi return nil, err } - return NewGenericMongoRepository[*ProductMongo](db, DatabaseName, CollectionName), nil + return NewGenericMongoRepository[*ProductMongo]( + db, + DatabaseName, + CollectionName, + ), nil } func seedAndMigration(ctx context.Context, db *mongo.Client) error { diff --git a/internal/pkg/otel/tracing/consts.go b/internal/pkg/otel/constants/consts.go similarity index 77% rename from internal/pkg/otel/tracing/consts.go rename to internal/pkg/otel/constants/consts.go index 251219d2..ab77589d 100644 --- a/internal/pkg/otel/tracing/consts.go +++ b/internal/pkg/otel/constants/consts.go @@ -1,4 +1,4 @@ -package tracing +package constants const ( TraceId = "general.trace-id" @@ -6,5 +6,4 @@ const ( ParentSpanId = "general.parent-span-id" Traceparent = "general.traceparent" Timestamp = "general.timestamp" - ErrorMessage = "general.error_message" ) diff --git a/internal/pkg/otel/constants/telemetry_attributes/app/app.go b/internal/pkg/otel/constants/telemetry_attributes/app/app.go new file mode 100644 index 00000000..cf48edc5 --- /dev/null +++ b/internal/pkg/otel/constants/telemetry_attributes/app/app.go @@ -0,0 +1,26 @@ +package app + +const ( + DefaultSourceName = "app" + Consumer = "app.consumer" + EventHandler = "app.event-handler" + Subscription = "app.subscription" + Stream = "app.stream" + Partition = "app.partition" + Request = "app.request" + RequestName = "app.request_name" + RequestResultName = "app.request_result_name" + RequestResult = "app.request_result" + Command = "app.command" + CommandName = "app.command_name" + CommandResult = "app.command_result" + CommandResultName = "app.command_result_name" + Query = "app.query" + QueryName = "app.query_name" + QueryResult = "app.query_result" + QueryResultName = "app.query_result_name" + Event = "app.event" + EventName = "app.event_name" + EventResult = "app.event_result" + EventResultName = "app.event_result_name" +) diff --git a/internal/pkg/otel/constants/telemetry_attributes/exception/exception.go b/internal/pkg/otel/constants/telemetry_attributes/exception/exception.go new file mode 100644 index 00000000..4124a08a --- /dev/null +++ b/internal/pkg/otel/constants/telemetry_attributes/exception/exception.go @@ -0,0 +1,8 @@ +package exception + +const ( + EventName = "exception" + Type = "exception.type" + Message = "exception.message" + Stacktrace = "exception.stacktrace" +) diff --git a/internal/pkg/otel/constants/telemetry_attributes/general/general.go b/internal/pkg/otel/constants/telemetry_attributes/general/general.go new file mode 100644 index 00000000..5bbe309c --- /dev/null +++ b/internal/pkg/otel/constants/telemetry_attributes/general/general.go @@ -0,0 +1 @@ +package general diff --git a/internal/pkg/otel/constants/telemetry_attributes/grpc/grpc.go b/internal/pkg/otel/constants/telemetry_attributes/grpc/grpc.go new file mode 100644 index 00000000..16cf53c6 --- /dev/null +++ b/internal/pkg/otel/constants/telemetry_attributes/grpc/grpc.go @@ -0,0 +1,3 @@ +package grpc + +// https://opentelemetry.io/docs/specs/otel/trace/semantic_conventions/rpc/ diff --git a/internal/pkg/otel/constants/telemetry_attributes/messaging/messaging.go b/internal/pkg/otel/constants/telemetry_attributes/messaging/messaging.go new file mode 100644 index 00000000..af5528e0 --- /dev/null +++ b/internal/pkg/otel/constants/telemetry_attributes/messaging/messaging.go @@ -0,0 +1,14 @@ +package messaging + +// https://opentelemetry.io/docs/specs/otel/trace/semantic_conventions/messaging/ +const ( + System = "messaging.system" + Destination = "messaging.destination" + DestinationKind = "messaging.destination_kind" + Url = "messaging.url" + MessageId = "messaging.message_id" + ConversationId = "messaging.conversation_id" + CorrelationId = "messaging.correlation_id" + CausationId = "messaging.causation_id" + Operation = "messaging.operation" +) diff --git a/internal/pkg/otel/constants/telemetry_attributes/net/net.go b/internal/pkg/otel/constants/telemetry_attributes/net/net.go new file mode 100644 index 00000000..b5e7cfcb --- /dev/null +++ b/internal/pkg/otel/constants/telemetry_attributes/net/net.go @@ -0,0 +1,11 @@ +package net + +const ( + Transport = "net.transport" + PeerIp = "net.peer.ip" + PeerPort = "net.peer.port" + PeerName = "net.peer.name" + HostIp = "net.host.ip" + HostPort = "net.host.port" + HostName = "net.host.name" +) diff --git a/internal/pkg/otel/constants/tracing/components/components.go b/internal/pkg/otel/constants/tracing/components/components.go new file mode 100644 index 00000000..3b1cd9d2 --- /dev/null +++ b/internal/pkg/otel/constants/tracing/components/components.go @@ -0,0 +1,8 @@ +package components + +const ( + CommandHandler = "command_handler" + RequestHandler = "request_handler" + QueryHandler = "query_handler" + EventHandler = "event_handler" +) diff --git a/internal/pkg/otel/constants/tracing/operations/operations.go b/internal/pkg/otel/constants/tracing/operations/operations.go new file mode 100644 index 00000000..4e5d524c --- /dev/null +++ b/internal/pkg/otel/constants/tracing/operations/operations.go @@ -0,0 +1,7 @@ +package operations + +const ( + Delete = "delete" + Read = "read" + Add = "add" +) diff --git a/internal/pkg/otel/metrics/pipelines/config.go b/internal/pkg/otel/metrics/pipelines/config.go new file mode 100644 index 00000000..e344c53d --- /dev/null +++ b/internal/pkg/otel/metrics/pipelines/config.go @@ -0,0 +1,43 @@ +package pipelines + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" +) + +type config struct { + logger logger.Logger + serviceName string +} + +var defaultConfig = &config{ + serviceName: "app", + logger: defaultLogger.GetLogger(), +} + +// Option specifies instrumentation configuration options. +type Option interface { + apply(*config) +} + +type optionFunc func(*config) + +func (o optionFunc) apply(c *config) { + o(c) +} + +func WithServiceName(v string) Option { + return optionFunc(func(cfg *config) { + if cfg.serviceName != "" { + cfg.serviceName = v + } + }) +} + +func WithLogger(l logger.Logger) Option { + return optionFunc(func(cfg *config) { + if cfg.logger != nil { + cfg.logger = l + } + }) +} diff --git a/internal/pkg/otel/metrics/pipelines/metrics_pipeline.go b/internal/pkg/otel/metrics/pipelines/metrics_pipeline.go new file mode 100644 index 00000000..60c0e19d --- /dev/null +++ b/internal/pkg/otel/metrics/pipelines/metrics_pipeline.go @@ -0,0 +1,145 @@ +package pipelines + +import ( + "context" + "fmt" + "strings" + "time" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants/telemetry_attributes/app" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" + attribute2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + + "github.com/mehdihadeli/go-mediatr" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" +) + +type metricsPipeline struct { + config *config + meter metrics.AppMetrics +} + +func NewMetricsPipeline( + appMetrics metrics.AppMetrics, + opts ...Option, +) mediatr.PipelineBehavior { + cfg := defaultConfig + for _, opt := range opts { + opt.apply(cfg) + } + + return &metricsPipeline{ + config: cfg, + meter: appMetrics, + } +} + +func (r *metricsPipeline) Handle( + ctx context.Context, + request interface{}, + next mediatr.RequestHandlerFunc, +) (interface{}, error) { + requestName := typeMapper.GetSnakeTypeName(request) + + requestNameAttribute := app.RequestName + requestAttribute := app.Request + requestResultName := app.RequestResultName + requestResult := app.RequestResult + requestType := "request" + + switch { + case strings.Contains(typeMapper.GetPackageName(request), "command") || strings.Contains(typeMapper.GetPackageName(request), "commands"): + requestNameAttribute = app.CommandName + requestAttribute = app.Command + requestResultName = app.CommandResultName + requestResult = app.CommandResult + requestType = "command" + case strings.Contains(typeMapper.GetPackageName(request), "query") || strings.Contains(typeMapper.GetPackageName(request), "queries"): + requestNameAttribute = app.QueryName + requestAttribute = app.Query + requestResultName = app.QueryResultName + requestResult = app.QueryResult + requestType = "query" + case strings.Contains(typeMapper.GetPackageName(request), "event") || strings.Contains(typeMapper.GetPackageName(request), "events"): + requestNameAttribute = app.EventName + requestAttribute = app.Event + requestResultName = app.EventResultName + requestResult = app.EventResult + requestType = "event" + } + + // Create instruments for success requests, failed requests, and duration + successRequestsCounter, err := r.meter.Int64Counter( + fmt.Sprintf("%s.success_total", requestName), + metric.WithUnit("count"), + metric.WithDescription( + fmt.Sprintf( + "Measures the number of success '%s' %s", + requestName, + requestType, + ), + ), + ) + if err != nil { + return nil, err + } + + failedRequestsCounter, err := r.meter.Int64Counter( + fmt.Sprintf("%s.failed_total", requestName), + metric.WithUnit("count"), + metric.WithDescription( + fmt.Sprintf( + "Measures the number of failed '%s' %s", + requestName, + requestType, + ), + ), + ) + if err != nil { + return nil, err + } + + durationValueRecorder, err := r.meter.Int64Histogram( + fmt.Sprintf("%s.duration", requestName), + metric.WithUnit("ms"), + metric.WithDescription( + fmt.Sprintf( + "Measures the duration of '%s' %s", + requestName, + requestType, + ), + ), + ) + if err != nil { + return nil, err + } + + // Start recording the duration + startTime := time.Now() + + response, err := next(ctx) + + // Calculate the duration + duration := time.Since(startTime).Milliseconds() + + responseName := typeMapper.GetSnakeTypeName(response) + opt := metric.WithAttributes( + attribute.String(requestNameAttribute, requestName), + attribute2.Object(requestAttribute, request), + attribute.String(requestResultName, responseName), + attribute2.Object(requestResult, response), + ) + + // Record metrics + if err == nil { + successRequestsCounter.Add(ctx, 1, opt) + } else { + failedRequestsCounter.Add(ctx, 1, opt) + } + + durationValueRecorder.Record(ctx, duration, opt) + + return response, err +} diff --git a/internal/pkg/otel/tracing/custom_tracer.go b/internal/pkg/otel/tracing/custom_tracer.go index 3c86d914..d4363e86 100644 --- a/internal/pkg/otel/tracing/custom_tracer.go +++ b/internal/pkg/otel/tracing/custom_tracer.go @@ -3,6 +3,8 @@ package tracing import ( "context" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" + "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/trace" ) @@ -22,7 +24,7 @@ func (c *appTracer) Start( ) (context.Context, trace.Span) { parentSpan := trace.SpanFromContext(ctx) if parentSpan != nil { - ContextWithParentSpan(ctx, parentSpan) + utils.ContextWithParentSpan(ctx, parentSpan) } return c.Tracer.Start(ctx, spanName, opts...) diff --git a/internal/pkg/otel/tracing/pipelines/config.go b/internal/pkg/otel/tracing/pipelines/config.go new file mode 100644 index 00000000..e344c53d --- /dev/null +++ b/internal/pkg/otel/tracing/pipelines/config.go @@ -0,0 +1,43 @@ +package pipelines + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" +) + +type config struct { + logger logger.Logger + serviceName string +} + +var defaultConfig = &config{ + serviceName: "app", + logger: defaultLogger.GetLogger(), +} + +// Option specifies instrumentation configuration options. +type Option interface { + apply(*config) +} + +type optionFunc func(*config) + +func (o optionFunc) apply(c *config) { + o(c) +} + +func WithServiceName(v string) Option { + return optionFunc(func(cfg *config) { + if cfg.serviceName != "" { + cfg.serviceName = v + } + }) +} + +func WithLogger(l logger.Logger) Option { + return optionFunc(func(cfg *config) { + if cfg.logger != nil { + cfg.logger = l + } + }) +} diff --git a/internal/pkg/otel/tracing/pipelines/tracing_pipeline.go b/internal/pkg/otel/tracing/pipelines/tracing_pipeline.go new file mode 100644 index 00000000..9b6851e2 --- /dev/null +++ b/internal/pkg/otel/tracing/pipelines/tracing_pipeline.go @@ -0,0 +1,109 @@ +package pipelines + +import ( + "context" + "fmt" + "strings" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants/telemetry_attributes/app" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants/tracing/components" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" + attribute2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + + "emperror.dev/errors" + "github.com/mehdihadeli/go-mediatr" + "go.opentelemetry.io/otel/attribute" +) + +type tracingPipeline struct { + config *config + tracer tracing.AppTracer +} + +func NewTracingPipeline( + appTracer tracing.AppTracer, + opts ...Option, +) mediatr.PipelineBehavior { + cfg := defaultConfig + for _, opt := range opts { + opt.apply(cfg) + } + + return &tracingPipeline{ + config: cfg, + tracer: appTracer, + } +} + +func (r *tracingPipeline) Handle( + ctx context.Context, + request interface{}, + next mediatr.RequestHandlerFunc, +) (interface{}, error) { + requestName := typeMapper.GetSnakeTypeName(request) + + componentName := components.RequestHandler + requestNameAttribute := app.RequestName + requestAttribute := app.Request + requestResultName := app.RequestResultName + requestResult := app.RequestResult + + switch { + case strings.Contains(typeMapper.GetPackageName(request), "command") || strings.Contains(typeMapper.GetPackageName(request), "commands"): + componentName = components.CommandHandler + requestNameAttribute = app.CommandName + requestAttribute = app.Command + requestResultName = app.CommandResultName + requestResult = app.CommandResult + case strings.Contains(typeMapper.GetPackageName(request), "query") || strings.Contains(typeMapper.GetPackageName(request), "queries"): + componentName = components.QueryHandler + requestNameAttribute = app.QueryName + requestAttribute = app.Query + requestResultName = app.QueryResultName + requestResult = app.QueryResult + case strings.Contains(typeMapper.GetPackageName(request), "event") || strings.Contains(typeMapper.GetPackageName(request), "events"): + componentName = components.EventHandler + requestNameAttribute = app.EventName + requestAttribute = app.Event + requestResultName = app.EventResultName + requestResult = app.EventResult + } + + operationName := fmt.Sprintf("%s_handler", requestName) + spanName := fmt.Sprintf( + "%s.%s/%s", + componentName, + operationName, + requestName, + ) // by convention + + // https://golang.org/pkg/context/#Context + newCtx, span := r.tracer.Start(ctx, spanName) + + defer span.End() + + span.SetAttributes( + attribute.String(requestNameAttribute, requestName), + attribute2.Object(requestAttribute, request), + ) + + response, err := next(newCtx) + + responseName := typeMapper.GetSnakeTypeName(response) + span.SetAttributes( + attribute.String(requestResultName, responseName), + attribute2.Object(requestResult, response), + ) + + err = utils.TraceStatusFromSpan( + span, + errors.WrapIf( + err, + fmt.Sprintf("Request '%s' failed.", requestName), + ), + ) + + return response, err +} diff --git a/internal/pkg/otel/tracing/utils.go b/internal/pkg/otel/tracing/utils.go deleted file mode 100644 index 6ca589e7..00000000 --- a/internal/pkg/otel/tracing/utils.go +++ /dev/null @@ -1,159 +0,0 @@ -package tracing - -import ( - "context" - "reflect" - - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" - errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" - - "github.com/ahmetb/go-linq/v3" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/codes" - trace2 "go.opentelemetry.io/otel/sdk/trace" - "go.opentelemetry.io/otel/trace" -) - -type traceContextKeyType int - -const parentSpanKey traceContextKeyType = iota + 1 - -func TraceErrFromContext(ctx context.Context, err error) error { - // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors - span := trace.SpanFromContext(ctx) - defer span.End() - - if err != nil { - stackTraceError := errorUtils.ErrorsWithStack(err) - span.SetStatus(codes.Error, "") - span.SetAttributes(attribute.String(ErrorMessage, stackTraceError)) - span.RecordError(err) - } - - return err -} - -func TraceErrFromSpan(span trace.Span, err error) error { - if err != nil { - stackTraceError := errorUtils.ErrorsWithStack(err) - span.SetStatus(codes.Error, "") - span.SetAttributes(attribute.String(ErrorMessage, stackTraceError)) - span.RecordError(err) - } - - return err -} - -func GetParentSpanContext(span trace.Span) trace.SpanContext { - readWriteSpan, ok := span.(trace2.ReadWriteSpan) - if !ok { - return *new(trace.SpanContext) - } - - return readWriteSpan.Parent() -} - -func ContextWithParentSpan(parent context.Context, span trace.Span) context.Context { - return context.WithValue(parent, parentSpanKey, span) -} - -func ParentSpanFromContext(ctx context.Context) trace.Span { - _, nopSpan := trace.NewNoopTracerProvider().Tracer("").Start(ctx, "") - if ctx == nil { - return nopSpan - } - if span, ok := ctx.Value(parentSpanKey).(trace.Span); ok { - return span - } - return nopSpan -} - -func CopyFromParentSpanAttribute( - ctx context.Context, - span trace.Span, - attributeName string, - parentAttributeName string, -) { - parentAtt := GetParentSpanAttribute(ctx, parentAttributeName) - if reflect.ValueOf(parentAtt).IsZero() { - return - } - span.SetAttributes(attribute.String(attributeName, parentAtt.Value.AsString())) -} - -func CopyFromParentSpanAttributeIfNotSet( - ctx context.Context, - span trace.Span, - attributeName string, - attributeValue string, - parentAttributeName string, -) { - if attributeValue != "" { - span.SetAttributes(attribute.String(attributeName, attributeValue)) - return - } - CopyFromParentSpanAttribute(ctx, span, attributeName, parentAttributeName) -} - -func GetParentSpanAttribute(ctx context.Context, parentAttributeName string) attribute.KeyValue { - parentSpan := ParentSpanFromContext(ctx) - readWriteSpan, ok := parentSpan.(trace2.ReadWriteSpan) - if !ok { - return *new(attribute.KeyValue) - } - att := linq.From(readWriteSpan.Attributes()). - FirstWithT(func(att attribute.KeyValue) bool { return string(att.Key) == parentAttributeName }) - - return att.(attribute.KeyValue) -} - -func GetSpanAttributeFromCurrentContext(ctx context.Context, attributeName string) attribute.KeyValue { - span := trace.SpanFromContext(ctx) - readWriteSpan, ok := span.(trace2.ReadWriteSpan) - if !ok { - return *new(attribute.KeyValue) - } - att := linq.From(readWriteSpan.Attributes()). - FirstWithT(func(att attribute.KeyValue) bool { return string(att.Key) == attributeName }) - - return att.(attribute.KeyValue) -} - -func GetSpanAttribute(span trace.Span, attributeName string) attribute.KeyValue { - readWriteSpan, ok := span.(trace2.ReadWriteSpan) - if !ok { - return *new(attribute.KeyValue) - } - att := linq.From(readWriteSpan.Attributes()). - FirstWithT(func(att attribute.KeyValue) bool { return string(att.Key) == attributeName }) - - return att.(attribute.KeyValue) -} - -func MapsToAttributes(maps map[string]interface{}) []attribute.KeyValue { - var att []attribute.KeyValue - for key, val := range maps { - switch val.(type) { - case string: - att = append(att, attribute.String(key, val.(string))) - case int64: - att = append(att, attribute.Int64(key, val.(int64))) - case int, int32: - att = append(att, attribute.Int(key, val.(int))) - case float64, float32: - att = append(att, attribute.Float64(key, val.(float64))) - case bool: - att = append(att, attribute.Bool(key, val.(bool))) - } - } - - return att -} - -func MetadataToSet(meta metadata.Metadata) attribute.Set { - var keyValue []attribute.KeyValue - for key, val := range meta { - keyValue = append(keyValue, attribute.String(key, val.(string))) - } - return attribute.NewSet(keyValue...) -} diff --git a/internal/pkg/otel/tracing/utils/utils.go b/internal/pkg/otel/tracing/utils/utils.go new file mode 100644 index 00000000..f36ed0b5 --- /dev/null +++ b/internal/pkg/otel/tracing/utils/utils.go @@ -0,0 +1,365 @@ +package utils + +import ( + "context" + "net/http" + "reflect" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/grpcErrors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/problemDetails" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants/telemetry_attributes/exception" + errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" + + "github.com/ahmetb/go-linq/v3" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" + trace2 "go.opentelemetry.io/otel/sdk/trace" + "go.opentelemetry.io/otel/semconv/v1.20.0/httpconv" + semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + "go.opentelemetry.io/otel/trace" +) + +type traceContextKeyType int + +const parentSpanKey traceContextKeyType = iota + 1 + +// HttpTraceStatusFromSpan create an error span if we have an error and a successful span when error is nil +func HttpTraceStatusFromSpan(span trace.Span, err error) error { + isError := err != nil + + if customErrors.IsCustomError(err) { + httpError := problemDetails.ParseError(err) + + return HttpTraceStatusFromSpanWithCode( + span, + err, + httpError.GetStatus(), + ) + } + + var ( + status int + code codes.Code + description = "" + ) + + if isError { + status = http.StatusInternalServerError + code = codes.Error + description = err.Error() + } else { + status = http.StatusOK + code = codes.Ok + } + + span.SetStatus(code, description) + span.SetAttributes( + semconv.HTTPStatusCode(status), + ) + + if isError { + stackTraceError := errorUtils.ErrorsWithStack(err) + + // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors + span.SetAttributes( + attribute.String(exception.Message, err.Error()), + attribute.String(exception.Stacktrace, stackTraceError), + ) + span.RecordError(err) + } + + return err +} + +func TraceStatusFromSpan(span trace.Span, err error) error { + isError := err != nil + + var ( + code codes.Code + description = "" + ) + + if isError { + code = codes.Error + description = err.Error() + } else { + code = codes.Ok + } + + span.SetStatus(code, description) + + if isError { + stackTraceError := errorUtils.ErrorsWithStack(err) + + // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors + span.SetAttributes( + attribute.String(exception.Message, err.Error()), + attribute.String(exception.Stacktrace, stackTraceError), + ) + span.RecordError(err) + } + + return err +} + +func TraceErrStatusFromSpan(span trace.Span, err error) error { + isError := err != nil + + span.SetStatus(codes.Error, err.Error()) + + if isError { + stackTraceError := errorUtils.ErrorsWithStack(err) + + // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors + span.SetAttributes( + attribute.String(exception.Message, err.Error()), + attribute.String(exception.Stacktrace, stackTraceError), + ) + span.RecordError(err) + } + + return err +} + +// HttpTraceStatusFromSpanWithCode create an error span with specific status code if we have an error and a successful span when error is nil with a specific status +func HttpTraceStatusFromSpanWithCode( + span trace.Span, + err error, + code int, +) error { + if err != nil { + stackTraceError := errorUtils.ErrorsWithStack(err) + + // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors + span.SetAttributes( + attribute.String(exception.Message, err.Error()), + attribute.String(exception.Stacktrace, stackTraceError), + ) + span.RecordError(err) + } + + if code > 0 { + // httpconv doesn't exist in semconv v1.21.0, and it moved to `opentelemetry-go-contrib` pkg + // https://github.com/open-telemetry/opentelemetry-go/pull/4362 + // https://github.com/open-telemetry/opentelemetry-go/issues/4081 + // using ClientStatus instead of ServerStatus for consideration of 4xx status as error + span.SetStatus(httpconv.ClientStatus(code)) + span.SetAttributes(semconv.HTTPStatusCode(code)) + } else { + span.SetStatus(codes.Error, "") + span.SetAttributes(semconv.HTTPStatusCode(http.StatusInternalServerError)) + } + + return err +} + +// HttpTraceStatusFromContext create an error span if we have an error and a successful span when error is nil +func HttpTraceStatusFromContext(ctx context.Context, err error) error { + // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors + span := trace.SpanFromContext(ctx) + + defer span.End() + + return HttpTraceStatusFromSpan(span, err) +} + +func TraceStatusFromContext(ctx context.Context, err error) error { + // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors + span := trace.SpanFromContext(ctx) + + defer span.End() + + return TraceStatusFromSpan(span, err) +} + +func TraceErrStatusFromContext(ctx context.Context, err error) error { + // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors + span := trace.SpanFromContext(ctx) + + defer span.End() + + return TraceErrStatusFromSpan(span, err) +} + +// GrpcTraceErrFromSpan setting span with status error with error message +func GrpcTraceErrFromSpan(span trace.Span, err error) error { + isError := err != nil + + span.SetStatus(codes.Error, err.Error()) + + if isError { + stackTraceError := errorUtils.ErrorsWithStack(err) + // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors + span.SetAttributes( + attribute.String(exception.Message, err.Error()), + attribute.String(exception.Stacktrace, stackTraceError), + ) + + if customErrors.IsCustomError(err) { + grpcErr := grpcErrors.ParseError(err) + span.SetAttributes( + semconv.RPCGRPCStatusCodeKey.Int(int(grpcErr.GetStatus())), + ) + } + + span.RecordError(err) + } + + return err +} + +// GrpcTraceErrFromSpanWithCode setting span with status error with error message +func GrpcTraceErrFromSpanWithCode(span trace.Span, err error, code int) error { + isError := err != nil + + span.SetStatus(codes.Error, err.Error()) + + if isError { + stackTraceError := errorUtils.ErrorsWithStack(err) + // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors + span.SetAttributes( + attribute.String(exception.Message, err.Error()), + attribute.String(exception.Stacktrace, stackTraceError), + ) + span.SetAttributes(semconv.RPCGRPCStatusCodeKey.Int(code)) + span.RecordError(err) + } + + return err +} + +func GetParentSpanContext(span trace.Span) trace.SpanContext { + readWriteSpan, ok := span.(trace2.ReadWriteSpan) + if !ok { + return *new(trace.SpanContext) + } + + return readWriteSpan.Parent() +} + +func ContextWithParentSpan( + parent context.Context, + span trace.Span, +) context.Context { + return context.WithValue(parent, parentSpanKey, span) +} + +func ParentSpanFromContext(ctx context.Context) trace.Span { + _, nopSpan := trace.NewNoopTracerProvider().Tracer("").Start(ctx, "") + if ctx == nil { + return nopSpan + } + + if span, ok := ctx.Value(parentSpanKey).(trace.Span); ok { + return span + } + + return nopSpan +} + +func CopyFromParentSpanAttribute( + ctx context.Context, + span trace.Span, + attributeName string, + parentAttributeName string, +) { + parentAtt := GetParentSpanAttribute(ctx, parentAttributeName) + if reflect.ValueOf(parentAtt).IsZero() { + return + } + + span.SetAttributes( + attribute.String(attributeName, parentAtt.Value.AsString()), + ) +} + +func CopyFromParentSpanAttributeIfNotSet( + ctx context.Context, + span trace.Span, + attributeName string, + attributeValue string, + parentAttributeName string, +) { + if attributeValue != "" { + span.SetAttributes(attribute.String(attributeName, attributeValue)) + return + } + CopyFromParentSpanAttribute(ctx, span, attributeName, parentAttributeName) +} + +func GetParentSpanAttribute( + ctx context.Context, + parentAttributeName string, +) attribute.KeyValue { + parentSpan := ParentSpanFromContext(ctx) + readWriteSpan, ok := parentSpan.(trace2.ReadWriteSpan) + if !ok { + return *new(attribute.KeyValue) + } + att := linq.From(readWriteSpan.Attributes()). + FirstWithT(func(att attribute.KeyValue) bool { return string(att.Key) == parentAttributeName }) + + return att.(attribute.KeyValue) +} + +func GetSpanAttributeFromCurrentContext( + ctx context.Context, + attributeName string, +) attribute.KeyValue { + span := trace.SpanFromContext(ctx) + readWriteSpan, ok := span.(trace2.ReadWriteSpan) + if !ok { + return *new(attribute.KeyValue) + } + att := linq.From(readWriteSpan.Attributes()). + FirstWithT(func(att attribute.KeyValue) bool { return string(att.Key) == attributeName }) + + return att.(attribute.KeyValue) +} + +func GetSpanAttribute( + span trace.Span, + attributeName string, +) attribute.KeyValue { + readWriteSpan, ok := span.(trace2.ReadWriteSpan) + if !ok { + return *new(attribute.KeyValue) + } + + att := linq.From(readWriteSpan.Attributes()). + FirstWithT(func(att attribute.KeyValue) bool { return string(att.Key) == attributeName }) + + return att.(attribute.KeyValue) +} + +func MapsToAttributes(maps map[string]interface{}) []attribute.KeyValue { + var att []attribute.KeyValue + + for key, val := range maps { + switch val.(type) { + case string: + att = append(att, attribute.String(key, val.(string))) + case int64: + att = append(att, attribute.Int64(key, val.(int64))) + case int, int32: + att = append(att, attribute.Int(key, val.(int))) + case float64, float32: + att = append(att, attribute.Float64(key, val.(float64))) + case bool: + att = append(att, attribute.Bool(key, val.(bool))) + } + } + + return att +} + +func MetadataToSet(meta metadata.Metadata) attribute.Set { + var keyValue []attribute.KeyValue + for key, val := range meta { + keyValue = append(keyValue, attribute.String(key, val.(string))) + } + + return attribute.NewSet(keyValue...) +} diff --git a/internal/pkg/rabbitmq/bus/rabbitmq_bus_test.go b/internal/pkg/rabbitmq/bus/rabbitmq_bus_test.go index 57258b13..65831517 100644 --- a/internal/pkg/rabbitmq/bus/rabbitmq_bus_test.go +++ b/internal/pkg/rabbitmq/bus/rabbitmq_bus_test.go @@ -30,8 +30,9 @@ func Test_AddRabbitMQ(t *testing.T) { fakeConsumer2 := consumer.NewRabbitMQFakeTestConsumerHandler[*ProducerConsumerMessage]() fakeConsumer3 := consumer.NewRabbitMQFakeTestConsumerHandler[*ProducerConsumerMessage]() - defaultLogger2.SetupDefaultLogger() - serializer := serializer.NewDefaultEventSerializer(json.NewDefaultSerializer()) + serializer := serializer.NewDefaultEventSerializer( + json.NewDefaultSerializer(), + ) rabbitmqOptions := &config.RabbitmqOptions{ RabbitmqHostOptions: &config.RabbitmqHostOptions{ @@ -44,24 +45,35 @@ func Test_AddRabbitMQ(t *testing.T) { conn, err := types.NewRabbitMQConnection(rabbitmqOptions) require.NoError(t, err) - b, err := NewRabbitmqBus(rabbitmqOptions, serializer, defaultLogger2.Logger, conn, + b, err := NewRabbitmqBus( + rabbitmqOptions, + serializer, + defaultLogger2.GetLogger(), + conn, func(builder configurations.RabbitMQConfigurationBuilder) { builder.AddProducer( ProducerConsumerMessage{}, func(builder producerConfigurations.RabbitMQProducerConfigurationBuilder) { }, ) - builder.AddConsumer(ProducerConsumerMessage{}, + builder.AddConsumer( + ProducerConsumerMessage{}, func(builder consumerConfigurations.RabbitMQConsumerConfigurationBuilder) { builder.WithHandlers(func(consumerHandlerBuilder messageConsumer.ConsumerHandlerConfigurationBuilder) { - consumerHandlerBuilder.AddHandler(NewTestMessageHandler()) - consumerHandlerBuilder.AddHandler(NewTestMessageHandler2()) + consumerHandlerBuilder.AddHandler( + NewTestMessageHandler(), + ) + consumerHandlerBuilder.AddHandler( + NewTestMessageHandler2(), + ) }). WIthPipelines(func(consumerPipelineBuilder pipeline.ConsumerPipelineConfigurationBuilder) { consumerPipelineBuilder.AddPipeline(NewPipeline1()) }) - }) - }) + }, + ) + }, + ) require.NoError(t, err) @@ -159,7 +171,10 @@ func (p Pipeline1) Handle( ) error { fmt.Println("PipelineBehaviourTest.Handled") - fmt.Printf("pipeline got a message with id '%s'", consumerContext.Message().GeMessageId()) + fmt.Printf( + "pipeline got a message with id '%s'", + consumerContext.Message().GeMessageId(), + ) err := next() if err != nil { diff --git a/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go b/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go index 6d4f0ad8..4ed61939 100644 --- a/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go +++ b/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go @@ -30,24 +30,19 @@ func Test_Consume_Message(t *testing.T) { defer errorUtils.HandlePanic() ctx := context.Background() - defaultLogger2.SetupDefaultLogger() eventSerializer := serializer.NewDefaultEventSerializer(json.NewDefaultSerializer()) tp, err := tracing.NewOtelTracing(&tracing.TracingOptions{ ServiceName: "test", Enabled: true, AlwaysOnSampler: true, - JaegerExporterOptions: &tracing.JaegerExporterOptions{ - AgentHost: "localhost", - AgentPort: "6831", - }, ZipkinExporterOptions: &tracing.ZipkinExporterOptions{ Url: "http://localhost:9411/api/v2/spans", }, }, environemnt.Development) require.NoError(t, err) - defer tp.TracerProvider.Shutdown(ctx) + defer tp.Shutdown(ctx) conn, err := types.NewRabbitMQConnection(&config.RabbitmqOptions{ RabbitmqHostOptions: &config.RabbitmqHostOptions{ @@ -71,7 +66,7 @@ func Test_Consume_Message(t *testing.T) { conn, builder.Build(), eventSerializer, - defaultLogger2.Logger, + defaultLogger2.GetLogger(), ) require.NoError(t, err) @@ -88,7 +83,7 @@ func Test_Consume_Message(t *testing.T) { rabbitmqProducer, err := producer.NewRabbitMQProducer( conn, nil, - defaultLogger2.Logger, + defaultLogger2.GetLogger(), eventSerializer) require.NoError(t, err) diff --git a/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go b/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go index 1c0dcf30..a2c2c4d4 100644 --- a/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go +++ b/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go @@ -21,8 +21,9 @@ import ( func Test_Publish_Message(t *testing.T) { testUtils.SkipCI(t) - defaultLogger.SetupDefaultLogger() - eventSerializer := serializer.NewDefaultEventSerializer(json.NewDefaultSerializer()) + eventSerializer := serializer.NewDefaultEventSerializer( + json.NewDefaultSerializer(), + ) ctx := context.Background() tp, err := tracing.NewOtelTracing( @@ -30,9 +31,8 @@ func Test_Publish_Message(t *testing.T) { ServiceName: "test", Enabled: true, AlwaysOnSampler: true, - JaegerExporterOptions: &tracing.JaegerExporterOptions{ - AgentHost: "localhost", - AgentPort: "6831", + ZipkinExporterOptions: &tracing.ZipkinExporterOptions{ + Url: "http://localhost:9411/api/v2/spans", }, }, environemnt.Development, @@ -40,7 +40,7 @@ func Test_Publish_Message(t *testing.T) { if err != nil { return } - defer tp.TracerProvider.Shutdown(ctx) + defer tp.Shutdown(ctx) conn, err := types.NewRabbitMQConnection(&config.RabbitmqOptions{ RabbitmqHostOptions: &config.RabbitmqHostOptions{ @@ -55,7 +55,7 @@ func Test_Publish_Message(t *testing.T) { rabbitmqProducer, err := NewRabbitMQProducer( conn, nil, - defaultLogger.Logger, + defaultLogger.GetLogger(), eventSerializer, ) require.NoError(t, err) diff --git a/internal/pkg/rabbitmq/types/connection.go b/internal/pkg/rabbitmq/types/connection.go index a1dc869d..5f77d835 100644 --- a/internal/pkg/rabbitmq/types/connection.go +++ b/internal/pkg/rabbitmq/types/connection.go @@ -131,13 +131,17 @@ func (c *internalConnection) handleReconnecting() { select { case err := <-c.errConnectionChan: if err != nil { - defaultLogger.Logger.Info("Rabbitmq Connection Reconnecting started") + defaultLogger.GetLogger(). + Info("Rabbitmq Connection Reconnecting started") err := c.connect() if err != nil { - defaultLogger.Logger.Error(fmt.Sprintf("Error in reconnecting, %s", err)) + defaultLogger.GetLogger(). + Error(fmt.Sprintf("Error in reconnecting, %s", err)) continue } - defaultLogger.Logger.Info("Rabbitmq Connection Reconnected") + + defaultLogger.GetLogger(). + Info("Rabbitmq Connection Reconnected") c.isConnected = true c.reconnectedChan <- struct{}{} continue diff --git a/internal/pkg/reflection/type_mappper/type_mapper.go b/internal/pkg/reflection/type_mappper/type_mapper.go index 759b56b8..713986b6 100644 --- a/internal/pkg/reflection/type_mappper/type_mapper.go +++ b/internal/pkg/reflection/type_mappper/type_mapper.go @@ -9,6 +9,8 @@ import ( "reflect" "strings" "unsafe" + + "github.com/iancoleman/strcase" ) var ( @@ -32,7 +34,8 @@ func discoverTypes() { for _, off := range offs { emptyInterface := (*emptyInterface)(unsafe.Pointer(&typ)) emptyInterface.data = resolveTypeOff(rodata, off) - if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct { + if typ.Kind() == reflect.Ptr && + typ.Elem().Kind() == reflect.Struct { // just discover pointer types, but we also register this pointer type actual struct type to the registry loadedTypePtr := typ loadedType := typ.Elem() @@ -105,7 +108,9 @@ func TypesByName(typeName string) []reflect.Type { return nil } -func TypeByNameAndImplementedInterface[TInterface interface{}](typeName string) reflect.Type { +func TypeByNameAndImplementedInterface[TInterface interface{}]( + typeName string, +) reflect.Type { // https://stackoverflow.com/questions/7132848/how-to-get-the-reflect-type-of-an-interface implementedInterface := GetTypeFromGeneric[TInterface]() if types, ok := types[typeName]; ok { @@ -170,6 +175,25 @@ func GetTypeName(input interface{}) string { return fmt.Sprintf("*%s", t.Elem().Name()) } +// GetNonePointerTypeName returns the name of the type without its package name and its pointer +func GetNonePointerTypeName(input interface{}) string { + t := reflect.TypeOf(input) + if t.Kind() != reflect.Ptr { + return t.Name() + } + + return t.Elem().Name() +} + +func GetSnakeTypeName(input interface{}) string { + t := reflect.TypeOf(input) + if t.Kind() != reflect.Ptr { + return t.Name() + } + + return strcase.ToSnake(t.Elem().Name()) +} + func GetTypeNameByT[T any]() string { t := reflect.TypeOf((*T)(nil)).Elem() if t.Kind() != reflect.Ptr { @@ -204,6 +228,19 @@ func TypeByPackageName(pkgPath string, name string) reflect.Type { return nil } +func GetPackageName(value interface{}) string { + inputType := reflect.TypeOf(value) + if inputType.Kind() == reflect.Ptr { + inputType = inputType.Elem() + } + + packagePath := inputType.PkgPath() + + parts := strings.Split(packagePath, "/") + + return parts[len(parts)-1] +} + func TypesByPackageName(pkgPath string, name string) []reflect.Type { if pkgTypes, ok := packages[pkgPath]; ok { return pkgTypes[name] @@ -261,7 +298,9 @@ func InstanceByTypeName(name string) interface{} { return getInstanceFromType(typ) } -func InstanceByTypeNameAndImplementedInterface[TInterface interface{}](name string) interface{} { +func InstanceByTypeNameAndImplementedInterface[TInterface interface{}]( + name string, +) interface{} { typ := TypeByNameAndImplementedInterface[TInterface](name) return getInstanceFromType(typ) diff --git a/internal/pkg/reflection/type_mappper/type_mapper_test.go b/internal/pkg/reflection/type_mappper/type_mapper_test.go index 36141d6b..d204ddeb 100644 --- a/internal/pkg/reflection/type_mappper/type_mapper_test.go +++ b/internal/pkg/reflection/type_mappper/type_mapper_test.go @@ -44,6 +44,12 @@ func TestTypes(t *testing.T) { typeName3 := GetTypeName(s2) typeName4 := GetTypeName(s) + pkName := GetPackageName(&Test{}) + pkName2 := GetPackageName(Test{}) + + assert.Equal(t, "typeMapper", pkName) + assert.Equal(t, "typeMapper", pkName2) + assert.Equal(t, "typeMapper.Test", typeName) assert.Equal(t, "*typeMapper.Test", typeName2) assert.Equal(t, "*Test", typeName3) diff --git a/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_container_test.go b/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_container_test.go index 954ccf0d..0278cc2e 100644 --- a/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_container_test.go +++ b/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_container_test.go @@ -22,11 +22,10 @@ import ( func Test_RabbitMQ_Container(t *testing.T) { ctx := context.Background() fakeConsumer := consumer.NewRabbitMQFakeTestConsumerHandler[*ProducerConsumerMessage]() - defaultLogger.SetupDefaultLogger() eventSerializer := serializer.NewDefaultEventSerializer(json.NewDefaultSerializer()) rabbitmq, err := NewRabbitMQDockerTest( - defaultLogger.Logger, + defaultLogger.GetLogger(), ).Start(ctx, t, eventSerializer, func(builder rabbitmqConfigurations.RabbitMQConfigurationBuilder) { builder.AddConsumer(ProducerConsumerMessage{}, func(consumerBuilder consumerConfigurations.RabbitMQConsumerConfigurationBuilder) { diff --git a/internal/pkg/test/containers/testcontainer/eventstoredb/eveentstoredb_container_test.go b/internal/pkg/test/containers/testcontainer/eventstoredb/eveentstoredb_container_test.go index e85211d0..5a0438b0 100644 --- a/internal/pkg/test/containers/testcontainer/eventstoredb/eveentstoredb_container_test.go +++ b/internal/pkg/test/containers/testcontainer/eventstoredb/eveentstoredb_container_test.go @@ -11,9 +11,7 @@ import ( ) func Test_Custom_EventStoreDB_Container(t *testing.T) { - defaultLogger.SetupDefaultLogger() - - esdbInstance, err := NewEventstoreDBTestContainers(defaultLogger.Logger).Start(context.Background(), t) + esdbInstance, err := NewEventstoreDBTestContainers(defaultLogger.GetLogger()).Start(context.Background(), t) require.NoError(t, err) assert.NotNil(t, esdbInstance) diff --git a/internal/pkg/test/containers/testcontainer/gorm/gorm_container_test.go b/internal/pkg/test/containers/testcontainer/gorm/gorm_container_test.go index e394f8ff..9ed659dc 100644 --- a/internal/pkg/test/containers/testcontainer/gorm/gorm_container_test.go +++ b/internal/pkg/test/containers/testcontainer/gorm/gorm_container_test.go @@ -18,9 +18,8 @@ import ( func Test_Custom_Gorm_Container(t *testing.T) { ctx := context.Background() - defaultLogger.SetupDefaultLogger() - gorm, err := NewGormTestContainers(defaultLogger.Logger).Start(ctx, t) + gorm, err := NewGormTestContainers(defaultLogger.GetLogger()).Start(ctx, t) require.NoError(t, err) assert.NotNil(t, gorm) diff --git a/internal/pkg/test/containers/testcontainer/mongo/mongo_container_test.go b/internal/pkg/test/containers/testcontainer/mongo/mongo_container_test.go index 958c88a4..fb0c8b8f 100644 --- a/internal/pkg/test/containers/testcontainer/mongo/mongo_container_test.go +++ b/internal/pkg/test/containers/testcontainer/mongo/mongo_container_test.go @@ -11,9 +11,9 @@ import ( ) func Test_Custom_Mongo_Container(t *testing.T) { - defaultLogger.SetupDefaultLogger() - - mongo, err := NewMongoTestContainers(defaultLogger.Logger).Start(context.Background(), t) + mongo, err := NewMongoTestContainers( + defaultLogger.GetLogger(), + ).Start(context.Background(), t) require.NoError(t, err) assert.NotNil(t, mongo) diff --git a/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_container_test.go b/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_container_test.go index 7f6d7436..2488b5e7 100644 --- a/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_container_test.go +++ b/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_container_test.go @@ -11,9 +11,9 @@ import ( ) func Test_Custom_PostgresPgx_Container(t *testing.T) { - defaultLogger.SetupDefaultLogger() - - gorm, err := NewPostgresPgxContainers(defaultLogger.Logger).Start(context.Background(), t) + gorm, err := NewPostgresPgxContainers( + defaultLogger.GetLogger(), + ).Start(context.Background(), t) require.NoError(t, err) assert.NotNil(t, gorm) diff --git a/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_container_test.go b/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_container_test.go index 81840d62..db6716ef 100644 --- a/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_container_test.go +++ b/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_container_test.go @@ -22,11 +22,10 @@ import ( func Test_Custom_RabbitMQ_Container(t *testing.T) { ctx := context.Background() fakeConsumer := consumer.NewRabbitMQFakeTestConsumerHandler[*ProducerConsumerMessage]() - defaultLogger.SetupDefaultLogger() eventSerializer := serializer.NewDefaultEventSerializer(json.NewDefaultSerializer()) rabbitmq, err := NewRabbitMQTestContainers( - defaultLogger.Logger, + defaultLogger.GetLogger(), ).Start(ctx, t, eventSerializer, func(builder rabbitmqConfigurations.RabbitMQConfigurationBuilder) { builder.AddConsumer(ProducerConsumerMessage{}, func(consumerBuilder consumerConfigurations.RabbitMQConsumerConfigurationBuilder) { diff --git a/internal/pkg/test/containers/testcontainer/redis/redis_container_test.go b/internal/pkg/test/containers/testcontainer/redis/redis_container_test.go index 07d0ea78..fd05ece6 100644 --- a/internal/pkg/test/containers/testcontainer/redis/redis_container_test.go +++ b/internal/pkg/test/containers/testcontainer/redis/redis_container_test.go @@ -11,9 +11,7 @@ import ( ) func Test_Custom_Redis_Container(t *testing.T) { - defaultLogger.SetupDefaultLogger() - - redis, err := NewRedisTestContainers(defaultLogger.Logger).Start(context.Background(), t) + redis, err := NewRedisTestContainers(defaultLogger.GetLogger()).Start(context.Background(), t) require.NoError(t, err) assert.NotNil(t, redis) diff --git a/internal/pkg/utils/error_utils/errors.go b/internal/pkg/utils/error_utils/errors.go index a704ed6e..48337c6b 100644 --- a/internal/pkg/utils/error_utils/errors.go +++ b/internal/pkg/utils/error_utils/errors.go @@ -94,6 +94,7 @@ func RootStackTrace(err error) string { func HandlePanic() { if r := recover(); r != nil { - defaultLogger.Logger.Error("stacktrace from panic: \n" + string(debug.Stack())) + defaultLogger.GetLogger(). + Error("stacktrace from panic: \n" + string(debug.Stack())) } } diff --git a/internal/services/catalog_read_service/go.mod b/internal/services/catalog_read_service/go.mod index 5540387e..bed94a78 100644 --- a/internal/services/catalog_read_service/go.mod +++ b/internal/services/catalog_read_service/go.mod @@ -13,7 +13,7 @@ require ( github.com/go-playground/validator v9.31.0+incompatible github.com/labstack/echo/v4 v4.11.1 github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg v0.0.0-20230831075934-be8df319f588 - github.com/mehdihadeli/go-mediatr v1.1.10 + github.com/mehdihadeli/go-mediatr v1.2.0 github.com/michaelklishin/rabbit-hole v1.5.0 github.com/pterm/pterm v0.12.69 github.com/redis/go-redis/v9 v9.2.1 diff --git a/internal/services/catalog_read_service/go.sum b/internal/services/catalog_read_service/go.sum index 2bd81eec..4049ad4d 100644 --- a/internal/services/catalog_read_service/go.sum +++ b/internal/services/catalog_read_service/go.sum @@ -520,6 +520,8 @@ github.com/mcuadros/go-defaults v1.2.0 h1:FODb8WSf0uGaY8elWJAkoLL0Ri6AlZ1bFlenk5 github.com/mcuadros/go-defaults v1.2.0/go.mod h1:WEZtHEVIGYVDqkKSWBdWKUVdRyKlMfulPaGDWIVeCWY= github.com/mehdihadeli/go-mediatr v1.1.10 h1:NAzg4065c90lgYeb+Vzbd2WKH0tUFpxzL0mpx6hkU/A= github.com/mehdihadeli/go-mediatr v1.1.10/go.mod h1:lwgZl7qVL/RKomObBblhG3uEte/r4nJDV95Vd+nGrMw= +github.com/mehdihadeli/go-mediatr v1.2.0 h1:XkzYF/uGfW4pwPWYAxKyY+mO6l989PbmCQWSYHuCZtU= +github.com/mehdihadeli/go-mediatr v1.2.0/go.mod h1:I9LuExxAKz6cTDJyP/SSDSmkHaPHK1/usnvEXjUY47k= github.com/michaelklishin/rabbit-hole v1.5.0 h1:Bex27BiFDsijCM9D0ezSHqyy0kehpYHuNKaPqq/a4RM= github.com/michaelklishin/rabbit-hole v1.5.0/go.mod h1:vvI1uOitYZi0O5HEGXhaWC1XT80Gy+HvFheJ+5Krlhk= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= diff --git a/internal/services/catalog_read_service/internal/products/data/repositories/mongo_product_repository.go b/internal/services/catalog_read_service/internal/products/data/repositories/mongo_product_repository.go index 25673369..e0399656 100644 --- a/internal/services/catalog_read_service/internal/products/data/repositories/mongo_product_repository.go +++ b/internal/services/catalog_read_service/internal/products/data/repositories/mongo_product_repository.go @@ -17,6 +17,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb/repository" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + utils2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" data2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/models" @@ -61,7 +62,7 @@ func (p *mongoProductRepository) GetAllProducts( // https://www.mongodb.com/docs/drivers/go/current/fundamentals/crud/read-operations/query-document/ result, err := p.mongoGenericRepository.GetAll(ctx, listQuery) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, errors.WrapIf( err, @@ -91,7 +92,7 @@ func (p *mongoProductRepository) SearchProducts( result, err := p.mongoGenericRepository.Search(ctx, searchText, listQuery) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, errors.WrapIf( err, @@ -128,7 +129,7 @@ func (p *mongoProductRepository) GetProductById( product, err := p.mongoGenericRepository.GetById(ctx, id) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, errors.WrapIf( err, @@ -164,7 +165,7 @@ func (p *mongoProductRepository) GetProductByProductId( map[string]interface{}{"productId": uuid}, ) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, errors.WrapIf( err, @@ -198,7 +199,7 @@ func (p *mongoProductRepository) CreateProduct( err := p.mongoGenericRepository.Add(ctx, product) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, errors.WrapIf( err, @@ -230,7 +231,7 @@ func (p *mongoProductRepository) UpdateProduct( err := p.mongoGenericRepository.Update(ctx, updateProduct) // https://www.mongodb.com/docs/manual/reference/method/db.collection.findOneAndUpdate/ if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, errors.WrapIf( err, @@ -266,7 +267,7 @@ func (p *mongoProductRepository) DeleteProductByID(ctx context.Context, uuid str err = p.mongoGenericRepository.Delete(ctx, id) if err != nil { - return tracing.TraceErrFromSpan(span, errors.WrapIf(err, fmt.Sprintf( + return utils2.TraceErrFromSpan(span, errors.WrapIf(err, fmt.Sprintf( "[mongoProductRepository_DeleteProductByID.FindOneAndDelete] error in deleting product with id %s from the database.", uuid, ))) diff --git a/internal/services/catalog_read_service/internal/products/data/repositories/redis_product_repository.go b/internal/services/catalog_read_service/internal/products/data/repositories/redis_product_repository.go index c7634164..c35f6954 100644 --- a/internal/services/catalog_read_service/internal/products/data/repositories/redis_product_repository.go +++ b/internal/services/catalog_read_service/internal/products/data/repositories/redis_product_repository.go @@ -8,6 +8,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/models" @@ -46,7 +47,7 @@ func (r *redisProductRepository) PutProduct( productBytes, err := json.Marshal(product) if err != nil { - return tracing.TraceErrFromSpan( + return utils.TraceErrFromSpan( span, errors.WrapIf( err, @@ -56,7 +57,7 @@ func (r *redisProductRepository) PutProduct( } if err := r.redisClient.HSetNX(ctx, r.getRedisProductPrefixKey(), key, productBytes).Err(); err != nil { - return tracing.TraceErrFromSpan( + return utils.TraceErrFromSpan( span, errors.WrapIf( err, @@ -102,7 +103,7 @@ func (r *redisProductRepository) GetProductById( return nil, nil } - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, errors.WrapIf( err, @@ -116,7 +117,7 @@ func (r *redisProductRepository) GetProductById( var product models.Product if err := json.Unmarshal(productBytes, &product); err != nil { - return nil, tracing.TraceErrFromSpan(span, err) + return nil, utils.TraceErrFromSpan(span, err) } span.SetAttributes(attribute.Object("Product", product)) @@ -145,7 +146,7 @@ func (r *redisProductRepository) DeleteProduct(ctx context.Context, key string) defer span.End() if err := r.redisClient.HDel(ctx, r.getRedisProductPrefixKey(), key).Err(); err != nil { - return tracing.TraceErrFromSpan( + return utils.TraceErrFromSpan( span, errors.WrapIf( err, @@ -175,7 +176,7 @@ func (r *redisProductRepository) DeleteAllProducts(ctx context.Context) error { defer span.End() if err := r.redisClient.Del(ctx, r.getRedisProductPrefixKey()).Err(); err != nil { - return tracing.TraceErrFromSpan( + return utils.TraceErrFromSpan( span, errors.WrapIf( err, diff --git a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/commands/create_product_handler.go b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/commands/create_product_handler.go index b3db69bf..b9eb6365 100644 --- a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/commands/create_product_handler.go +++ b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/commands/create_product_handler.go @@ -8,6 +8,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/models" @@ -57,7 +58,7 @@ func (c *CreateProductHandler) Handle( createdProduct, err := c.mongoRepository.CreateProduct(ctx, product) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, @@ -68,7 +69,7 @@ func (c *CreateProductHandler) Handle( err = c.redisRepository.PutProduct(ctx, createdProduct.Id, createdProduct) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, diff --git a/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/commands/delete_product_handler.go b/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/commands/delete_product_handler.go index ae581fd2..adc70314 100644 --- a/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/commands/delete_product_handler.go +++ b/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/commands/delete_product_handler.go @@ -8,6 +8,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" "github.com/mehdihadeli/go-mediatr" @@ -47,7 +48,7 @@ func (c *DeleteProductCommand) Handle( defer span.End() if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, @@ -59,7 +60,7 @@ func (c *DeleteProductCommand) Handle( ) } if product == nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewNotFoundErrorWrap( err, @@ -72,7 +73,7 @@ func (c *DeleteProductCommand) Handle( } if err := c.mongoRepository.DeleteProductByID(ctx, product.Id); err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, @@ -85,7 +86,7 @@ func (c *DeleteProductCommand) Handle( err = c.redisRepository.DeleteProduct(ctx, product.Id) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, diff --git a/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/queries/get_product_by_id_handler.go b/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/queries/get_product_by_id_handler.go index ded05f65..291a4a08 100644 --- a/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/queries/get_product_by_id_handler.go +++ b/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/queries/get_product_by_id_handler.go @@ -9,6 +9,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/dto" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/dtos" @@ -53,7 +54,7 @@ func (q *GetProductByIdHandler) Handle( defer span.End() if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, @@ -71,7 +72,7 @@ func (q *GetProductByIdHandler) Handle( var mongoProduct *models.Product mongoProduct, err = q.mongoRepository.GetProductById(ctx, query.Id.String()) if err != nil { - return nil, tracing.TraceErrFromSpan(span, customErrors.NewApplicationErrorWrap(err, fmt.Sprintf("[GetProductByIdHandler_Handle.GetProductById] error in getting product with id %d in the mongo repository", query.Id))) + return nil, utils.TraceErrFromSpan(span, customErrors.NewApplicationErrorWrap(err, fmt.Sprintf("[GetProductByIdHandler_Handle.GetProductById] error in getting product with id %d in the mongo repository", query.Id))) } if mongoProduct == nil { mongoProduct, err = q.mongoRepository.GetProductByProductId(ctx, query.Id.String()) @@ -83,13 +84,13 @@ func (q *GetProductByIdHandler) Handle( product = mongoProduct err = q.redisRepository.PutProduct(ctx, product.Id, product) if err != nil { - return new(dtos.GetProductByIdResponseDto), tracing.TraceErrFromSpan(span, err) + return new(dtos.GetProductByIdResponseDto), utils.TraceErrFromSpan(span, err) } } productDto, err := mapper.Map[*dto.ProductDto](product) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, diff --git a/internal/services/catalog_read_service/internal/products/features/getting_products/v1/queries/get_products_handler.go b/internal/services/catalog_read_service/internal/products/features/getting_products/v1/queries/get_products_handler.go index 85e8034d..12894870 100644 --- a/internal/services/catalog_read_service/internal/products/features/getting_products/v1/queries/get_products_handler.go +++ b/internal/services/catalog_read_service/internal/products/features/getting_products/v1/queries/get_products_handler.go @@ -7,6 +7,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + utils2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/dto" @@ -37,7 +38,7 @@ func (c *GetProductsHandler) Handle( products, err := c.mongoRepository.GetAllProducts(ctx, query.ListQuery) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, @@ -48,7 +49,7 @@ func (c *GetProductsHandler) Handle( listResultDto, err := utils.ListResultToListResultDto[*dto.ProductDto](products) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, diff --git a/internal/services/catalog_read_service/internal/products/features/searching_products/v1/queries/search_products_handler.go b/internal/services/catalog_read_service/internal/products/features/searching_products/v1/queries/search_products_handler.go index 588fe8d4..abbf5cbc 100644 --- a/internal/services/catalog_read_service/internal/products/features/searching_products/v1/queries/search_products_handler.go +++ b/internal/services/catalog_read_service/internal/products/features/searching_products/v1/queries/search_products_handler.go @@ -7,6 +7,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + utils2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/dto" @@ -37,7 +38,7 @@ func (c *SearchProductsHandler) Handle( products, err := c.mongoRepository.SearchProducts(ctx, query.SearchText, query.ListQuery) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, @@ -48,7 +49,7 @@ func (c *SearchProductsHandler) Handle( listResultDto, err := utils.ListResultToListResultDto[*dto.ProductDto](products) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, diff --git a/internal/services/catalog_read_service/internal/products/features/updating_products/v1/commands/update_product_handler.go b/internal/services/catalog_read_service/internal/products/features/updating_products/v1/commands/update_product_handler.go index 90faf295..1ef5f9c2 100644 --- a/internal/services/catalog_read_service/internal/products/features/updating_products/v1/commands/update_product_handler.go +++ b/internal/services/catalog_read_service/internal/products/features/updating_products/v1/commands/update_product_handler.go @@ -8,6 +8,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" "github.com/mehdihadeli/go-mediatr" @@ -46,7 +47,7 @@ func (c *UpdateProductHandler) Handle( product, err := c.mongoRepository.GetProductByProductId(ctx, command.ProductId.String()) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, @@ -59,7 +60,7 @@ func (c *UpdateProductHandler) Handle( } if product == nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewNotFoundErrorWrap( err, @@ -78,7 +79,7 @@ func (c *UpdateProductHandler) Handle( _, err = c.mongoRepository.UpdateProduct(ctx, product) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, @@ -89,7 +90,7 @@ func (c *UpdateProductHandler) Handle( err = c.redisRepository.PutProduct(ctx, product.Id, product) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, diff --git a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go b/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go index 6bf878de..54fcd8e9 100644 --- a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go +++ b/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go @@ -2,20 +2,44 @@ package infrastructure import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/pipelines" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" + pipelines2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/pipelines" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" + tracingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/pipelines" + + "github.com/mehdihadeli/go-mediatr" ) type InfrastructureConfigurator struct { contracts.Application } -func NewInfrastructureConfigurator(app contracts.Application) *InfrastructureConfigurator { +func NewInfrastructureConfigurator( + app contracts.Application, +) *InfrastructureConfigurator { return &InfrastructureConfigurator{ Application: app, } } func (ic *InfrastructureConfigurator) ConfigInfrastructures() { - ic.ResolveFunc(func() error { - return nil - }) + ic.ResolveFunc( + func(logger logger.Logger, tracer tracing.AppTracer, metrics metrics.AppMetrics) error { + err := mediatr.RegisterRequestPipelineBehaviors( + pipelines.NewLoggingPipeline(logger), + tracingpipelines.NewTracingPipeline( + tracer, + tracingpipelines.WithLogger(logger), + ), + pipelines2.NewMetricsPipeline( + metrics, + pipelines2.WithLogger(logger), + ), + ) + + return err + }, + ) } diff --git a/internal/services/catalog_write_service/cmd/migration/main.go b/internal/services/catalog_write_service/cmd/migration/main.go index 216fd3f4..fd0b4284 100644 --- a/internal/services/catalog_write_service/cmd/migration/main.go +++ b/internal/services/catalog_write_service/cmd/migration/main.go @@ -39,7 +39,7 @@ var ( if len(args) == 0 { cmd.SetArgs([]string{"up"}) if err := cmd.Execute(); err != nil { - defaultLogger.Logger.Error(err) + defaultLogger.GetLogger().Error(err) os.Exit(1) } } @@ -66,7 +66,7 @@ var ( func executeMigration(cmd *cobra.Command, commandType migration.CommandType) { version, err := cmd.Flags().GetUint("version") if err != nil { - defaultLogger.Logger.Fatal(err) + defaultLogger.GetLogger().Fatal(err) } app := fx.New( @@ -79,37 +79,37 @@ func executeMigration(cmd *cobra.Command, commandType migration.CommandType) { //gomigrate.Module, // use go-migrate library for migration goose.Module, - fx.Invoke(func(migrationRunner contracts.PostgresMigrationRunner, logger logger.Logger) { - logger.Info("Migration process started...") - switch commandType { - case migration.Up: - err = migrationRunner.Up(context.Background(), version) - case migration.Down: - err = migrationRunner.Down(context.Background(), version) - } - if err != nil { - logger.Fatalf("migration failed, err: %s", err) - } - logger.Info("Migration completed...") - }), + fx.Invoke( + func(migrationRunner contracts.PostgresMigrationRunner, logger logger.Logger) { + logger.Info("Migration process started...") + switch commandType { + case migration.Up: + err = migrationRunner.Up(context.Background(), version) + case migration.Down: + err = migrationRunner.Down(context.Background(), version) + } + if err != nil { + logger.Fatalf("migration failed, err: %s", err) + } + logger.Info("Migration completed...") + }, + ), ) err = app.Start(context.Background()) if err != nil { - defaultLogger.Logger.Fatal(err) + defaultLogger.GetLogger().Fatal(err) } err = app.Stop(context.Background()) if err != nil { - defaultLogger.Logger.Fatal(err) + defaultLogger.GetLogger().Fatal(err) } } func main() { - defaultLogger.SetupDefaultLogger() - if err := rootCmd.Execute(); err != nil { - defaultLogger.Logger.Error(err) + defaultLogger.GetLogger().Error(err) os.Exit(1) } } diff --git a/internal/services/catalog_write_service/go.mod b/internal/services/catalog_write_service/go.mod index 251ddbc2..36bb9f9a 100644 --- a/internal/services/catalog_write_service/go.mod +++ b/internal/services/catalog_write_service/go.mod @@ -16,7 +16,7 @@ require ( github.com/labstack/echo/v4 v4.11.1 github.com/lib/pq v1.10.9 github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg v0.0.0-20230831075934-be8df319f588 - github.com/mehdihadeli/go-mediatr v1.1.10 + github.com/mehdihadeli/go-mediatr v1.2.0 github.com/michaelklishin/rabbit-hole v1.5.0 github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.28.0 diff --git a/internal/services/catalog_write_service/go.sum b/internal/services/catalog_write_service/go.sum index 56ac8692..5a7f4c18 100644 --- a/internal/services/catalog_write_service/go.sum +++ b/internal/services/catalog_write_service/go.sum @@ -542,6 +542,8 @@ github.com/mcuadros/go-defaults v1.2.0 h1:FODb8WSf0uGaY8elWJAkoLL0Ri6AlZ1bFlenk5 github.com/mcuadros/go-defaults v1.2.0/go.mod h1:WEZtHEVIGYVDqkKSWBdWKUVdRyKlMfulPaGDWIVeCWY= github.com/mehdihadeli/go-mediatr v1.1.10 h1:NAzg4065c90lgYeb+Vzbd2WKH0tUFpxzL0mpx6hkU/A= github.com/mehdihadeli/go-mediatr v1.1.10/go.mod h1:lwgZl7qVL/RKomObBblhG3uEte/r4nJDV95Vd+nGrMw= +github.com/mehdihadeli/go-mediatr v1.2.0 h1:XkzYF/uGfW4pwPWYAxKyY+mO6l989PbmCQWSYHuCZtU= +github.com/mehdihadeli/go-mediatr v1.2.0/go.mod h1:I9LuExxAKz6cTDJyP/SSDSmkHaPHK1/usnvEXjUY47k= github.com/michaelklishin/rabbit-hole v1.5.0 h1:Bex27BiFDsijCM9D0ezSHqyy0kehpYHuNKaPqq/a4RM= github.com/michaelklishin/rabbit-hole v1.5.0/go.mod h1:vvI1uOitYZi0O5HEGXhaWC1XT80Gy+HvFheJ+5Krlhk= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= diff --git a/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go b/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go index 2fa22c82..fc7443af 100644 --- a/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go +++ b/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go @@ -9,6 +9,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + utils2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" data2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" @@ -46,20 +47,23 @@ func (p *postgresProductRepository) GetAllProducts( defer span.End() result, err := p.gormGenericRepository.GetAll(ctx, listQuery) + err = utils2.TraceStatusFromContext( + ctx, + errors.WrapIf( + err, + "error in the paginate", + ), + ) + if err != nil { - return nil, tracing.TraceErrFromContext( - ctx, - errors.WrapIf( - err, - "[postgresProductRepository_GetAllProducts.Paginate] error in the paginate", - ), - ) + return nil, err } p.log.Infow( - "[postgresProductRepository.GetAllProducts] products loaded", + "products loaded", logger.Fields{"ProductsResult": result}, ) + span.SetAttributes(attribute.Object("ProductsResult", result)) return result, nil @@ -75,19 +79,20 @@ func (p *postgresProductRepository) SearchProducts( defer span.End() result, err := p.gormGenericRepository.Search(ctx, searchText, listQuery) + err = utils2.TraceStatusFromContext( + ctx, + errors.WrapIf( + err, + "error in the paginate", + ), + ) if err != nil { - return nil, tracing.TraceErrFromContext( - ctx, - errors.WrapIf( - err, - "[postgresProductRepository_SearchProducts.Paginate] error in the paginate", - ), - ) + return nil, err } p.log.Infow( fmt.Sprintf( - "[postgresProductRepository.SearchProducts] products loaded for search term '%s'", + "products loaded for search term '%s'", searchText, ), logger.Fields{"ProductsResult": result}, @@ -106,23 +111,25 @@ func (p *postgresProductRepository) GetProductById( defer span.End() product, err := p.gormGenericRepository.GetById(ctx, uuid) - if err != nil { - return nil, tracing.TraceErrFromSpan( - span, - errors.WrapIf( - err, - fmt.Sprintf( - "[postgresProductRepository_GetProductById.First] can't find the product with id %s into the database.", - uuid, - ), + err = utils2.TraceStatusFromSpan( + span, + errors.WrapIf( + err, + fmt.Sprintf( + "can't find the product with id %s into the database.", + uuid, ), - ) + ), + ) + + if err != nil { + return nil, err } span.SetAttributes(attribute.Object("Product", product)) p.log.Infow( fmt.Sprintf( - "[postgresProductRepository.GetProductById] product with id %s laoded", + "product with id %s laoded", uuid.String(), ), logger.Fields{"Product": product, "ProductId": uuid}, @@ -139,20 +146,21 @@ func (p *postgresProductRepository) CreateProduct( defer span.End() err := p.gormGenericRepository.Add(ctx, product) + err = utils2.TraceStatusFromSpan( + span, + errors.WrapIf( + err, + "error in the inserting product into the database.", + ), + ) if err != nil { - return nil, tracing.TraceErrFromSpan( - span, - errors.WrapIf( - err, - "[postgresProductRepository_CreateProduct.Create] error in the inserting product into the database.", - ), - ) + return nil, err } span.SetAttributes(attribute.Object("Product", product)) p.log.Infow( fmt.Sprintf( - "[postgresProductRepository.CreateProduct] product with id '%s' created", + "product with id '%s' created", product.ProductId, ), logger.Fields{"Product": product, "ProductId": product.ProductId}, @@ -169,47 +177,57 @@ func (p *postgresProductRepository) UpdateProduct( defer span.End() err := p.gormGenericRepository.Update(ctx, updateProduct) - if err != nil { - return nil, tracing.TraceErrFromSpan( - span, - errors.WrapIf( - err, - fmt.Sprintf( - "[postgresProductRepository_UpdateProduct.Save] error in updating product with id %s into the database.", - updateProduct.ProductId, - ), + err = utils2.TraceStatusFromSpan( + span, + errors.WrapIf( + err, + fmt.Sprintf( + "error in updating product with id %s into the database.", + updateProduct.ProductId, ), - ) + ), + ) + + if err != nil { + return nil, err } span.SetAttributes(attribute.Object("Product", updateProduct)) p.log.Infow( fmt.Sprintf( - "[postgresProductRepository.UpdateProduct] product with id '%s' updated", + "product with id '%s' updated", updateProduct.ProductId, ), - logger.Fields{"Product": updateProduct, "ProductId": updateProduct.ProductId}, + logger.Fields{ + "Product": updateProduct, + "ProductId": updateProduct.ProductId, + }, ) return updateProduct, nil } -func (p *postgresProductRepository) DeleteProductByID(ctx context.Context, uuid uuid.UUID) error { +func (p *postgresProductRepository) DeleteProductByID( + ctx context.Context, + uuid uuid.UUID, +) error { ctx, span := p.tracer.Start(ctx, "postgresProductRepository.UpdateProduct") span.SetAttributes(attribute2.String("ProductId", uuid.String())) defer span.End() err := p.gormGenericRepository.Delete(ctx, uuid) + err = utils2.TraceStatusFromSpan(span, errors.WrapIf(err, fmt.Sprintf( + "error in the deleting product with id %s into the database.", + uuid, + ))) + if err != nil { - return tracing.TraceErrFromSpan(span, errors.WrapIf(err, fmt.Sprintf( - "[postgresProductRepository_DeleteProductByID.Delete] error in the deleting product with id %s into the database.", - uuid, - ))) + return err } p.log.Infow( fmt.Sprintf( - "[postgresProductRepository.DeleteProductByID] product with id %s deleted", + "product with id %s deleted", uuid, ), logger.Fields{"Product": uuid}, diff --git a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/commands/create_product.go b/internal/services/catalog_write_service/internal/products/features/creating_product/v1/commands/create_product.go index 624cfe1c..e55d861f 100644 --- a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/commands/create_product.go +++ b/internal/services/catalog_write_service/internal/products/features/creating_product/v1/commands/create_product.go @@ -18,7 +18,11 @@ type CreateProduct struct { CreatedAt time.Time } -func NewCreateProduct(name string, description string, price float64) (*CreateProduct, error) { +func NewCreateProduct( + name string, + description string, + price float64, +) (*CreateProduct, error) { command := &CreateProduct{ ProductID: uuid.NewV4(), Name: name, @@ -34,11 +38,24 @@ func NewCreateProduct(name string, description string, price float64) (*CreatePr } func (c *CreateProduct) Validate() error { - return validation.ValidateStruct(c, + return validation.ValidateStruct( + c, validation.Field(&c.ProductID, validation.Required), - validation.Field(&c.Name, validation.Required, validation.Length(0, 255)), - validation.Field(&c.Description, validation.Required, validation.Length(0, 5000)), - validation.Field(&c.Price, validation.Required, validation.Min(0.0).Exclusive()), + validation.Field( + &c.Name, + validation.Required, + validation.Length(0, 255), + ), + validation.Field( + &c.Description, + validation.Required, + validation.Length(0, 5000), + ), + validation.Field( + &c.Price, + validation.Required, + validation.Min(0.0).Exclusive(), + ), validation.Field(&c.CreatedAt, validation.Required), ) } diff --git a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/commands/create_product_handler.go b/internal/services/catalog_write_service/internal/products/features/creating_product/v1/commands/create_product_handler.go index 217d1425..705773fe 100644 --- a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/commands/create_product_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/creating_product/v1/commands/create_product_handler.go @@ -10,14 +10,11 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/dtos" integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/events/integration_events" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" - - attribute2 "go.opentelemetry.io/otel/attribute" ) type CreateProductHandler struct { @@ -45,11 +42,6 @@ func (c *CreateProductHandler) Handle( ctx context.Context, command *CreateProduct, ) (*dtos.CreateProductResponseDto, error) { - ctx, span := c.tracer.Start(ctx, "CreateProductHandler.Handle") - span.SetAttributes(attribute2.String("ProductId", command.ProductID.String())) - span.SetAttributes(attribute.Object("Command", command)) - defer span.End() - product := &models.Product{ ProductId: command.ProductID, Name: command.Name, @@ -61,25 +53,20 @@ func (c *CreateProductHandler) Handle( var createProductResult *dtos.CreateProductResponseDto err := c.uow.Do(ctx, func(catalogContext data.CatalogContext) error { - createdProduct, err := catalogContext.Products().CreateProduct(ctx, product) + createdProduct, err := catalogContext.Products(). + CreateProduct(ctx, product) if err != nil { - return tracing.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrapWithCode( - err, - http.StatusConflict, - "[CreateProductHandler.CreateProduct] product already exists", - ), + return customErrors.NewApplicationErrorWrapWithCode( + err, + http.StatusConflict, + "product already exists", ) } productDto, err := mapper.Map[*dtoV1.ProductDto](createdProduct) if err != nil { - return tracing.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[CreateProductHandler.Map] error in the mapping ProductDto", - ), + return customErrors.NewApplicationErrorWrap( + err, + "error in the mapping ProductDto", ) } @@ -87,33 +74,33 @@ func (c *CreateProductHandler) Handle( err = c.rabbitmqProducer.PublishMessage(ctx, productCreated, nil) if err != nil { - return tracing.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[CreateProductHandler.PublishMessage] error in publishing ProductCreated integration_events event", - ), + return customErrors.NewApplicationErrorWrap( + err, + "error in publishing ProductCreated integration_events event", ) } c.log.Infow( fmt.Sprintf( - "[CreateProductHandler.Handle] ProductCreated message with messageId `%s` published to the rabbitmq broker", + "ProductCreated message with messageId `%s` published to the rabbitmq broker", productCreated.MessageId, ), logger.Fields{"MessageId": productCreated.MessageId}, ) - createProductResult = &dtos.CreateProductResponseDto{ProductID: product.ProductId} - - span.SetAttributes(attribute.Object("CreateProductResultDto", createProductResult)) + createProductResult = &dtos.CreateProductResponseDto{ + ProductID: product.ProductId, + } c.log.Infow( fmt.Sprintf( - "[CreateProductHandler.Handle] product with id '%s' created", + "product with id '%s' created", command.ProductID, ), - logger.Fields{"ProductId": command.ProductID, "MessageId": productCreated.MessageId}, + logger.Fields{ + "ProductId": command.ProductID, + "MessageId": productCreated.MessageId, + }, ) return nil diff --git a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/dtos/create_product_response_dto.go b/internal/services/catalog_write_service/internal/products/features/creating_product/v1/dtos/create_product_response_dto.go index 02572e6a..e00a1ff9 100644 --- a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/dtos/create_product_response_dto.go +++ b/internal/services/catalog_write_service/internal/products/features/creating_product/v1/dtos/create_product_response_dto.go @@ -1,8 +1,16 @@ package dtos -import uuid "github.com/satori/go.uuid" +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/json" + + uuid "github.com/satori/go.uuid" +) // https://echo.labstack.com/guide/response/ type CreateProductResponseDto struct { ProductID uuid.UUID `json:"productId"` } + +func (c *CreateProductResponseDto) String() string { + return json.PrettyPrint(c) +} diff --git a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/endpoints/create_product_endpoint.go b/internal/services/catalog_write_service/internal/products/features/creating_product/v1/endpoints/create_product_endpoint.go index 66a444b4..07fadef3 100644 --- a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/endpoints/create_product_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/creating_product/v1/endpoints/create_product_endpoint.go @@ -1,11 +1,9 @@ package endpoints import ( - "fmt" "net/http" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/params" createProductCommand "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/commands" @@ -47,14 +45,10 @@ func (ep *createProductEndpoint) handler() echo.HandlerFunc { if err := c.Bind(request); err != nil { badRequestErr := customErrors.NewBadRequestErrorWrap( err, - "[createProductEndpoint_handler.Bind] error in the binding request", - ) - ep.Logger.Errorf( - fmt.Sprintf( - "[createProductEndpoint_handler.Bind] err: %v", - badRequestErr, - ), + "error in the binding request", ) + + return badRequestErr } command, err := createProductCommand.NewCreateProduct( @@ -65,15 +59,8 @@ func (ep *createProductEndpoint) handler() echo.HandlerFunc { if err != nil { validationErr := customErrors.NewValidationErrorWrap( err, - "[createProductEndpoint_handler.StructCtx] command validation failed", - ) - ep.Logger.Errorf( - fmt.Sprintf( - "[createProductEndpoint_handler.StructCtx] err: {%v}", - validationErr, - ), + "command validation failed", ) - return validationErr } @@ -82,19 +69,10 @@ func (ep *createProductEndpoint) handler() echo.HandlerFunc { command, ) if err != nil { - err = errors.WithMessage( + return errors.WithMessage( err, - "[createProductEndpoint_handler.Send] error in sending CreateProduct", - ) - ep.Logger.Errorw( - fmt.Sprintf( - "[createProductEndpoint_handler.Send] id: {%s}, err: {%v}", - command.ProductID, - err, - ), - logger.Fields{"ProductId": command.ProductID}, + "error in sending CreateProduct", ) - return err } return c.JSON(http.StatusCreated, result) diff --git a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/commands/delete_product_handler.go b/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/commands/delete_product_handler.go index d1aa93a8..e8a4f350 100644 --- a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/commands/delete_product_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/commands/delete_product_handler.go @@ -9,12 +9,10 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1/events/integration_events" "github.com/mehdihadeli/go-mediatr" - attribute2 "go.opentelemetry.io/otel/attribute" ) type DeleteProductHandler struct { @@ -42,38 +40,29 @@ func (c *DeleteProductHandler) Handle( ctx context.Context, command *DeleteProduct, ) (*mediatr.Unit, error) { - ctx, span := c.tracer.Start(ctx, "deleteProductHandler.Handle") - span.SetAttributes(attribute2.String("ProductId", command.ProductID.String())) - span.SetAttributes(attribute.Object("Command", command)) - defer span.End() - err := c.uow.Do(ctx, func(catalogContext data.CatalogContext) error { if err := catalogContext.Products().DeleteProductByID(ctx, command.ProductID); err != nil { - return tracing.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrapWithCode( - err, - http.StatusNotFound, - "[DeleteProductHandler_Handle.DeleteProductByID] product not found", - ), + return customErrors.NewApplicationErrorWrapWithCode( + err, + http.StatusNotFound, + "product not found", ) } - productDeleted := integrationEvents.NewProductDeletedV1(command.ProductID.String()) + productDeleted := integrationEvents.NewProductDeletedV1( + command.ProductID.String(), + ) err := c.rabbitmqProducer.PublishMessage(ctx, productDeleted, nil) if err != nil { - return tracing.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[DeleteProductHandler_Handle.PublishMessage] error in publishing 'ProductDeleted' message", - ), + return customErrors.NewApplicationErrorWrap( + err, + "error in publishing 'ProductDeleted' message", ) } c.log.Infow( fmt.Sprintf( - "[DeleteProductHandler.Handle] ProductDeleted message with messageId '%s' published to the rabbitmq broker", + "ProductDeleted message with messageId '%s' published to the rabbitmq broker", productDeleted.MessageId, ), logger.Fields{"MessageId": productDeleted.MessageId}, @@ -81,7 +70,7 @@ func (c *DeleteProductHandler) Handle( c.log.Infow( fmt.Sprintf( - "[DeleteProductHandler.Handle] product with id '%s' deleted", + "product with id '%s' deleted", command.ProductID, ), logger.Fields{"ProductId": command.ProductID}, diff --git a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/endpoints/delete_product_endpoint.go b/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/endpoints/delete_product_endpoint.go index d30cf015..e8cd7ecf 100644 --- a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/endpoints/delete_product_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/endpoints/delete_product_endpoint.go @@ -1,11 +1,9 @@ package endpoints import ( - "fmt" "net/http" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/params" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1/commands" @@ -48,11 +46,9 @@ func (ep *deleteProductEndpoint) handler() echo.HandlerFunc { if err := c.Bind(request); err != nil { badRequestErr := customErrors.NewBadRequestErrorWrap( err, - "[deleteProductEndpoint_handler.Bind] error in the binding request", - ) - ep.Logger.Errorf( - fmt.Sprintf("[deleteProductEndpoint_handler.Bind] err: %v", badRequestErr), + "error in the binding request", ) + return badRequestErr } @@ -60,30 +56,22 @@ func (ep *deleteProductEndpoint) handler() echo.HandlerFunc { if err != nil { validationErr := customErrors.NewValidationErrorWrap( err, - "[deleteProductEndpoint_handler.StructCtx] command validation failed", - ) - ep.Logger.Errorf( - fmt.Sprintf("[deleteProductEndpoint_handler.StructCtx] err: {%v}", validationErr), + "command validation failed", ) + return validationErr } - _, err = mediatr.Send[*commands.DeleteProduct, *mediatr.Unit](ctx, command) + _, err = mediatr.Send[*commands.DeleteProduct, *mediatr.Unit]( + ctx, + command, + ) if err != nil { - err = errors.WithMessage( + return errors.WithMessage( err, - "[deleteProductEndpoint_handler.Send] error in sending DeleteProduct", - ) - ep.Logger.Errorw( - fmt.Sprintf( - "[deleteProductEndpoint_handler.Send] id: {%s}, err: {%v}", - command.ProductID, - err, - ), - logger.Fields{"ProductId": command.ProductID}, + "error in sending DeleteProduct", ) - return err } return c.NoContent(http.StatusNoContent) diff --git a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/endpoints/get_product_by_id_endpoint.go b/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/endpoints/get_product_by_id_endpoint.go index 7a98ac58..bee89310 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/endpoints/get_product_by_id_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/endpoints/get_product_by_id_endpoint.go @@ -1,11 +1,9 @@ package endpoints import ( - "fmt" "net/http" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/params" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/dtos" @@ -48,11 +46,9 @@ func (ep *getProductByIdEndpoint) handler() echo.HandlerFunc { if err := c.Bind(request); err != nil { badRequestErr := customErrors.NewBadRequestErrorWrap( err, - "[getProductByIdEndpoint_handler.Bind] error in the binding request", - ) - ep.Logger.Errorf( - fmt.Sprintf("[getProductByIdEndpoint_handler.Bind] err: %v", badRequestErr), + "error in the binding request", ) + return badRequestErr } @@ -60,9 +56,9 @@ func (ep *getProductByIdEndpoint) handler() echo.HandlerFunc { if err != nil { validationErr := customErrors.NewValidationErrorWrap( err, - "[getProductByIdEndpoint_handler.StructCtx] query validation failed", + "query validation failed", ) - ep.Logger.Errorf("[getProductByIdEndpoint_handler.StructCtx] err: {%v}", validationErr) + return validationErr } @@ -71,19 +67,10 @@ func (ep *getProductByIdEndpoint) handler() echo.HandlerFunc { query, ) if err != nil { - err = errors.WithMessage( + return errors.WithMessage( err, - "[getProductByIdEndpoint_handler.Send] error in sending GetProductById", - ) - ep.Logger.Errorw( - fmt.Sprintf( - "[getProductByIdEndpoint_handler.Send] id: {%s}, err: {%v}", - query.ProductID, - err, - ), - logger.Fields{"ProductId": query.ProductID}, + "error in sending GetProductById", ) - return err } return c.JSON(http.StatusOK, queryResult) diff --git a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/queries/get_product_by_id_handler.go b/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/queries/get_product_by_id_handler.go index a61ab286..a7be089e 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/queries/get_product_by_id_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/queries/get_product_by_id_handler.go @@ -9,12 +9,9 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/dtos" - - attribute2 "go.opentelemetry.io/otel/attribute" ) type GetProductByIdHandler struct { @@ -35,40 +32,29 @@ func (q *GetProductByIdHandler) Handle( ctx context.Context, query *GetProductById, ) (*dtos.GetProductByIdResponseDto, error) { - ctx, span := q.tracer.Start(ctx, "GetProductByIdHandler.Handle") - span.SetAttributes(attribute.Object("Query", query)) - span.SetAttributes(attribute2.String("ProductId", query.ProductID.String())) - defer span.End() - product, err := q.pgRepo.GetProductById(ctx, query.ProductID) if err != nil { - return nil, tracing.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrapWithCode( - err, - http.StatusNotFound, - fmt.Sprintf( - "[GetProductByIdHandler_Handle.GetProductById] error in getting product with id %s in the repository", - query.ProductID.String(), - ), + return nil, customErrors.NewApplicationErrorWrapWithCode( + err, + http.StatusNotFound, + fmt.Sprintf( + "error in getting product with id %s in the repository", + query.ProductID.String(), ), ) } productDto, err := mapper.Map[*dtoV1.ProductDto](product) if err != nil { - return nil, tracing.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[GetProductByIdHandler_Handle.Map] error in the mapping product", - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in the mapping product", ) } q.log.Infow( fmt.Sprintf( - "[GetProductByIdHandler.Handle] product with id: {%s} fetched", + "product with id: {%s} fetched", query.ProductID, ), logger.Fields{"ProductId": query.ProductID.String()}, diff --git a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go index b057380e..0df6e389 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go @@ -1,7 +1,6 @@ package endpoints import ( - "fmt" "net/http" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" @@ -48,29 +47,19 @@ func (ep *getProductsEndpoint) handler() echo.HandlerFunc { if err != nil { badRequestErr := customErrors.NewBadRequestErrorWrap( err, - "[getProductsEndpoint_handler.GetListQueryFromCtx] error in getting data from query string", + "error in getting data from query string", ) - ep.Logger.Errorf( - fmt.Sprintf( - "[getProductsEndpoint_handler.GetListQueryFromCtx] err: %v", - badRequestErr, - ), - ) - return err + + return badRequestErr } request := &dtos.GetProductsRequestDto{ListQuery: listQuery} if err := c.Bind(request); err != nil { badRequestErr := customErrors.NewBadRequestErrorWrap( err, - "[getProductsEndpoint_handler.Bind] error in the binding request", - ) - ep.Logger.Errorf( - fmt.Sprintf( - "[getProductsEndpoint_handler.Bind] err: %v", - badRequestErr, - ), + "error in the binding request", ) + return badRequestErr } @@ -84,17 +73,10 @@ func (ep *getProductsEndpoint) handler() echo.HandlerFunc { query, ) if err != nil { - err = errors.WithMessage( + return errors.WithMessage( err, - "[getProductsEndpoint_handler.Send] error in sending GetProducts", + "error in sending GetProducts", ) - ep.Logger.Error( - fmt.Sprintf( - "[getProductsEndpoint_handler.Send] err: {%v}", - err, - ), - ) - return err } return c.JSON(http.StatusOK, queryResult) diff --git a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/queries/get_products_handler.go b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/queries/get_products_handler.go index 26b453dd..d1035d57 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/queries/get_products_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/queries/get_products_handler.go @@ -3,10 +3,8 @@ package queries import ( "context" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" @@ -31,33 +29,19 @@ func (c *GetProductsHandler) Handle( ctx context.Context, query *GetProducts, ) (*dtos.GetProductsResponseDto, error) { - ctx, span := c.tracer.Start(ctx, "GetProductsHandler.Handle") - span.SetAttributes(attribute.Object("Query", query)) - defer span.End() - products, err := c.pgRepo.GetAllProducts(ctx, query.ListQuery) if err != nil { - return nil, tracing.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[GetProductsHandler_Handle.GetAllProducts] error in getting products in the repository", - ), - ) + return nil, err } - listResultDto, err := utils.ListResultToListResultDto[*dto.ProductDto](products) + listResultDto, err := utils.ListResultToListResultDto[*dto.ProductDto]( + products, + ) if err != nil { - return nil, tracing.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[GetProductsHandler_Handle.ListResultToListResultDto] error in the mapping ListResultToListResultDto", - ), - ) + return nil, err } - c.log.Info("[GetProductsHandler.Handle] products fetched") + c.log.Info("products fetched") return &dtos.GetProductsResponseDto{Products: listResultDto}, nil } diff --git a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/endpoints/search_products_endpoint.go b/internal/services/catalog_write_service/internal/products/features/searching_product/v1/endpoints/search_products_endpoint.go index 2b3f8e5f..9ddfbec2 100644 --- a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/endpoints/search_products_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/searching_product/v1/endpoints/search_products_endpoint.go @@ -1,7 +1,6 @@ package endpoints import ( - "fmt" "net/http" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" @@ -48,36 +47,32 @@ func (ep *searchProductsEndpoint) handler() echo.HandlerFunc { if err != nil { badRequestErr := customErrors.NewBadRequestErrorWrap( err, - "[searchProductsEndpoint_handler.GetListQueryFromCtx] error in getting data from query string", + "error in getting data from query string", ) - ep.Logger.Errorf( - fmt.Sprintf( - "[searchProductsEndpoint_handler.GetListQueryFromCtx] err: %v", - badRequestErr, - ), - ) - return err + + return badRequestErr } request := &dtos.SearchProductsRequestDto{ListQuery: listQuery} if err := c.Bind(request); err != nil { badRequestErr := customErrors.NewBadRequestErrorWrap( err, - "[searchProductsEndpoint_handler.Bind] error in the binding request", - ) - ep.Logger.Errorf( - fmt.Sprintf("[searchProductsEndpoint_handler.Bind] err: %v", badRequestErr), + "error in the binding request", ) + return badRequestErr } - query, err := queries.NewSearchProducts(request.SearchText, request.ListQuery) + query, err := queries.NewSearchProducts( + request.SearchText, + request.ListQuery, + ) if err != nil { validationErr := customErrors.NewValidationErrorWrap( err, - "[searchProductsEndpoint_handler.StructCtx] query validation failed", + "query validation failed", ) - ep.Logger.Errorf("[searchProductsEndpoint_handler.StructCtx] err: {%v}", validationErr) + return validationErr } @@ -86,12 +81,10 @@ func (ep *searchProductsEndpoint) handler() echo.HandlerFunc { query, ) if err != nil { - err = errors.WithMessage( + return errors.WithMessage( err, - "[searchProductsEndpoint_handler.Send] error in sending SearchProducts", + "error in sending SearchProducts", ) - ep.Logger.Error(fmt.Sprintf("[searchProductsEndpoint_handler.Send] err: {%v}", err)) - return err } return c.JSON(http.StatusOK, queryResult) diff --git a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/queries/search_products_handler.go b/internal/services/catalog_write_service/internal/products/features/searching_product/v1/queries/search_products_handler.go index f81e8c06..62f75485 100644 --- a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/queries/search_products_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/searching_product/v1/queries/search_products_handler.go @@ -6,7 +6,6 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" @@ -31,33 +30,29 @@ func (c *SearchProductsHandler) Handle( ctx context.Context, query *SearchProducts, ) (*dtos.SearchProductsResponseDto, error) { - ctx, span := c.tracer.Start(ctx, "SearchProductsHandler.Handle") - span.SetAttributes(attribute.Object("Query", query)) - defer span.End() - - products, err := c.pgRepo.SearchProducts(ctx, query.SearchText, query.ListQuery) + products, err := c.pgRepo.SearchProducts( + ctx, + query.SearchText, + query.ListQuery, + ) if err != nil { - return nil, tracing.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[SearchProductsHandler_Handle.SearchProducts] error in searching products in the repository", - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in searching products in the repository", ) } - listResultDto, err := utils.ListResultToListResultDto[*dto.ProductDto](products) + listResultDto, err := utils.ListResultToListResultDto[*dto.ProductDto]( + products, + ) if err != nil { - return nil, tracing.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[SearchProductsHandler_Handle.ListResultToListResultDto] error in the mapping ListResultToListResultDto", - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in the mapping ListResultToListResultDto", ) } - c.log.Info("[SearchProductsHandler.Handle] products fetched") + c.log.Info("products fetched") return &dtos.SearchProductsResponseDto{Products: listResultDto}, nil } diff --git a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/commands/update_product_handler.go b/internal/services/catalog_write_service/internal/products/features/updating_product/v1/commands/update_product_handler.go index d6c6f9a1..f4971ef2 100644 --- a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/commands/update_product_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/updating_product/v1/commands/update_product_handler.go @@ -10,13 +10,11 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/events/integration_events" "github.com/mehdihadeli/go-mediatr" - attribute2 "go.opentelemetry.io/otel/attribute" ) type UpdateProductHandler struct { @@ -44,23 +42,16 @@ func (c *UpdateProductHandler) Handle( ctx context.Context, command *UpdateProduct, ) (*mediatr.Unit, error) { - ctx, span := c.tracer.Start(ctx, "UpdateProductHandler.Handle") - span.SetAttributes(attribute2.String("ProductId", command.ProductID.String())) - span.SetAttributes(attribute.Object("Command", command)) - defer span.End() - err := c.uow.Do(ctx, func(catalogContext data.CatalogContext) error { - product, err := catalogContext.Products().GetProductById(ctx, command.ProductID) + product, err := catalogContext.Products(). + GetProductById(ctx, command.ProductID) if err != nil { - return tracing.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrapWithCode( - err, - http.StatusNotFound, - fmt.Sprintf( - "[UpdateProductHandler_Handle.GetProductById] product with id %s not found", - command.ProductID, - ), + return customErrors.NewApplicationErrorWrapWithCode( + err, + http.StatusNotFound, + fmt.Sprintf( + "product with id %s not found", + command.ProductID, ), ) } @@ -70,25 +61,20 @@ func (c *UpdateProductHandler) Handle( product.Description = command.Description product.UpdatedAt = command.UpdatedAt - updatedProduct, err := catalogContext.Products().UpdateProduct(ctx, product) + updatedProduct, err := catalogContext.Products(). + UpdateProduct(ctx, product) if err != nil { - return tracing.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[UpdateProductHandler_Handle.UpdateProduct] error in updating product in the repository", - ), + return customErrors.NewApplicationErrorWrap( + err, + "error in updating product in the repository", ) } productDto, err := mapper.Map[*dto.ProductDto](updatedProduct) if err != nil { - return tracing.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[UpdateProductHandler_Handle.Map] error in the mapping ProductDto", - ), + return customErrors.NewApplicationErrorWrap( + err, + "error in the mapping ProductDto", ) } @@ -96,18 +82,15 @@ func (c *UpdateProductHandler) Handle( err = c.rabbitmqProducer.PublishMessage(ctx, productUpdated, nil) if err != nil { - return tracing.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[UpdateProductHandler_Handle.PublishMessage] error in publishing 'ProductUpdated' message", - ), + return customErrors.NewApplicationErrorWrap( + err, + "error in publishing 'ProductUpdated' message", ) } c.log.Infow( fmt.Sprintf( - "[UpdateProductHandler.Handle] product with id '%s' updated", + "product with id '%s' updated", command.ProductID, ), logger.Fields{"ProductId": command.ProductID}, @@ -115,7 +98,7 @@ func (c *UpdateProductHandler) Handle( c.log.Infow( fmt.Sprintf( - "[DeleteProductHandler.Handle] ProductUpdated message with messageId `%s` published to the rabbitmq broker", + "ProductUpdated message with messageId `%s` published to the rabbitmq broker", productUpdated.MessageId, ), logger.Fields{"MessageId": productUpdated.MessageId}, diff --git a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/endpoints/update_product_endpoint.go b/internal/services/catalog_write_service/internal/products/features/updating_product/v1/endpoints/update_product_endpoint.go index 333eb5b8..1a6dff7d 100644 --- a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/endpoints/update_product_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/updating_product/v1/endpoints/update_product_endpoint.go @@ -1,11 +1,9 @@ package endpoints import ( - "fmt" "net/http" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/params" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/commands" @@ -49,11 +47,9 @@ func (ep *updateProductEndpoint) handler() echo.HandlerFunc { if err := c.Bind(request); err != nil { badRequestErr := customErrors.NewBadRequestErrorWrap( err, - "[updateProductEndpoint_handler.Bind] error in the binding request", - ) - ep.Logger.Errorf( - fmt.Sprintf("[updateProductEndpoint_handler.Bind] err: %v", badRequestErr), + "error in the binding request", ) + return badRequestErr } @@ -66,29 +62,18 @@ func (ep *updateProductEndpoint) handler() echo.HandlerFunc { if err != nil { validationErr := customErrors.NewValidationErrorWrap( err, - "[updateProductEndpoint_handler.StructCtx] command validation failed", - ) - ep.Logger.Errorf( - fmt.Sprintf("[updateProductEndpoint_handler.StructCtx] err: {%v}", validationErr), + "command validation failed", ) + return validationErr } _, err = mediatr.Send[*commands.UpdateProduct, *mediatr.Unit](ctx, command) if err != nil { - err = errors.WithMessage( + return errors.WithMessage( err, - "[updateProductEndpoint_handler.Send] error in sending UpdateProduct", - ) - ep.Logger.Errorw( - fmt.Sprintf( - "[updateProductEndpoint_handler.Send] id: {%s}, err: {%v}", - command.ProductID, - err, - ), - logger.Fields{"ProductId": command.ProductID}, + "error in sending UpdateProduct", ) - return err } return c.NoContent(http.StatusNoContent) diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go index b3c5777b..f4022183 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go +++ b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go @@ -2,20 +2,44 @@ package infrastructure import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/pipelines" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" + pipelines2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/pipelines" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" + tracingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/pipelines" + + "github.com/mehdihadeli/go-mediatr" ) type InfrastructureConfigurator struct { contracts.Application } -func NewInfrastructureConfigurator(fxapp contracts.Application) *InfrastructureConfigurator { +func NewInfrastructureConfigurator( + fxapp contracts.Application, +) *InfrastructureConfigurator { return &InfrastructureConfigurator{ Application: fxapp, } } func (ic *InfrastructureConfigurator) ConfigInfrastructures() { - ic.ResolveFunc(func() error { - return nil - }) + ic.ResolveFunc( + func(logger logger.Logger, tracer tracing.AppTracer, metrics metrics.AppMetrics) error { + err := mediatr.RegisterRequestPipelineBehaviors( + pipelines.NewLoggingPipeline(logger), + tracingpipelines.NewTracingPipeline( + tracer, + tracingpipelines.WithLogger(logger), + ), + pipelines2.NewMetricsPipeline( + metrics, + pipelines2.WithLogger(logger), + ), + ) + + return err + }, + ) } diff --git a/internal/services/catalog_write_service/internal/shared/test_fixtures/unit_test/unit_test_fixture.go b/internal/services/catalog_write_service/internal/shared/test_fixtures/unit_test/unit_test_fixture.go index b55976d6..a74f5776 100644 --- a/internal/services/catalog_write_service/internal/shared/test_fixtures/unit_test/unit_test_fixture.go +++ b/internal/services/catalog_write_service/internal/shared/test_fixtures/unit_test/unit_test_fixture.go @@ -34,8 +34,7 @@ type UnitTestSharedFixture struct { func NewUnitTestSharedFixture(t *testing.T) *UnitTestSharedFixture { // we could use EmptyLogger if we don't want to log anything - defaultLogger.SetupDefaultLogger() - log := defaultLogger.Logger + log := defaultLogger.GetLogger() cfg := &config.AppOptions{} err := configMapper() diff --git a/internal/services/order_service/go.mod b/internal/services/order_service/go.mod index a71ac28c..bf950584 100644 --- a/internal/services/order_service/go.mod +++ b/internal/services/order_service/go.mod @@ -16,7 +16,7 @@ require ( github.com/goccy/go-json v0.10.2 github.com/labstack/echo/v4 v4.11.1 github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg v0.0.0-20230831075934-be8df319f588 - github.com/mehdihadeli/go-mediatr v1.1.10 + github.com/mehdihadeli/go-mediatr v1.2.0 github.com/michaelklishin/rabbit-hole v1.5.0 github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.28.0 diff --git a/internal/services/order_service/go.sum b/internal/services/order_service/go.sum index 9f1c3a91..09c7866e 100644 --- a/internal/services/order_service/go.sum +++ b/internal/services/order_service/go.sum @@ -519,6 +519,8 @@ github.com/mcuadros/go-defaults v1.2.0 h1:FODb8WSf0uGaY8elWJAkoLL0Ri6AlZ1bFlenk5 github.com/mcuadros/go-defaults v1.2.0/go.mod h1:WEZtHEVIGYVDqkKSWBdWKUVdRyKlMfulPaGDWIVeCWY= github.com/mehdihadeli/go-mediatr v1.1.10 h1:NAzg4065c90lgYeb+Vzbd2WKH0tUFpxzL0mpx6hkU/A= github.com/mehdihadeli/go-mediatr v1.1.10/go.mod h1:lwgZl7qVL/RKomObBblhG3uEte/r4nJDV95Vd+nGrMw= +github.com/mehdihadeli/go-mediatr v1.2.0 h1:XkzYF/uGfW4pwPWYAxKyY+mO6l989PbmCQWSYHuCZtU= +github.com/mehdihadeli/go-mediatr v1.2.0/go.mod h1:I9LuExxAKz6cTDJyP/SSDSmkHaPHK1/usnvEXjUY47k= github.com/michaelklishin/rabbit-hole v1.5.0 h1:Bex27BiFDsijCM9D0ezSHqyy0kehpYHuNKaPqq/a4RM= github.com/michaelklishin/rabbit-hole v1.5.0/go.mod h1:vvI1uOitYZi0O5HEGXhaWC1XT80Gy+HvFheJ+5Krlhk= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= diff --git a/internal/services/order_service/internal/orders/data/repositories/mongo_order_read_repository.go b/internal/services/order_service/internal/orders/data/repositories/mongo_order_read_repository.go index 7215d647..8407c0da 100644 --- a/internal/services/order_service/internal/orders/data/repositories/mongo_order_read_repository.go +++ b/internal/services/order_service/internal/orders/data/repositories/mongo_order_read_repository.go @@ -8,6 +8,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + utils2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/contracts/repositories" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/models/orders/read_models" @@ -57,7 +58,7 @@ func (m mongoOrderReadRepository) GetAllOrders( result, err := mongodb.Paginate[*read_models.OrderReadModel](ctx, listQuery, collection, nil) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, errors.WrapIf( err, @@ -98,7 +99,7 @@ func (m mongoOrderReadRepository) SearchOrders( result, err := mongodb.Paginate[*read_models.OrderReadModel](ctx, listQuery, collection, filter) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, errors.WrapIf( err, @@ -135,7 +136,7 @@ func (m mongoOrderReadRepository) GetOrderById( if err == mongo.ErrNoDocuments { return nil, nil } - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, errors.WrapIf( err, @@ -172,7 +173,7 @@ func (m mongoOrderReadRepository) GetOrderByOrderId( if err == mongo.ErrNoDocuments { return nil, nil } - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, errors.WrapIf( err, @@ -206,7 +207,7 @@ func (m mongoOrderReadRepository) CreateOrder( collection := m.mongoClient.Database(m.mongoOptions.Database).Collection(orderCollection) _, err := collection.InsertOne(ctx, order, &options.InsertOneOptions{}) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, errors.WrapIf( err, @@ -242,7 +243,7 @@ func (m mongoOrderReadRepository) UpdateOrder( var updated read_models.OrderReadModel if err := collection.FindOneAndUpdate(ctx, bson.M{"_id": order.OrderId}, bson.M{"$set": order}, ops).Decode(&updated); err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, errors.WrapIf( err, @@ -274,7 +275,7 @@ func (m mongoOrderReadRepository) DeleteOrderByID(ctx context.Context, uuid uuid collection := m.mongoClient.Database(m.mongoOptions.Database).Collection(orderCollection) if err := collection.FindOneAndDelete(ctx, bson.M{"_id": uuid.String()}).Err(); err != nil { - return tracing.TraceErrFromSpan(span, errors.WrapIf(err, fmt.Sprintf( + return utils2.TraceErrFromSpan(span, errors.WrapIf(err, fmt.Sprintf( "[mongoOrderReadRepository_DeleteOrderByID.FindOneAndDelete] error in deleting order with id %d from the database.", uuid, ))) diff --git a/internal/services/order_service/internal/orders/features/creating_order/v1/commands/create_order_handler.go b/internal/services/order_service/internal/orders/features/creating_order/v1/commands/create_order_handler.go index d00ebcc4..8956e662 100644 --- a/internal/services/order_service/internal/orders/features/creating_order/v1/commands/create_order_handler.go +++ b/internal/services/order_service/internal/orders/features/creating_order/v1/commands/create_order_handler.go @@ -10,6 +10,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" customAttribute "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/creating_order/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/models/orders/aggregate" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/models/orders/value_objects" @@ -43,7 +44,7 @@ func (c *CreateOrderHandler) Handle( shopItems, err := mapper.Map[[]*value_objects.ShopItem](command.ShopItems) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, @@ -61,7 +62,7 @@ func (c *CreateOrderHandler) Handle( command.CreatedAt, ) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, @@ -72,7 +73,7 @@ func (c *CreateOrderHandler) Handle( _, err = c.aggregateStore.Store(order, nil, ctx) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, diff --git a/internal/services/order_service/internal/orders/features/getting_order_by_id/v1/queries/get_order_by_id_handler.go b/internal/services/order_service/internal/orders/features/getting_order_by_id/v1/queries/get_order_by_id_handler.go index 2051893c..e2f4691e 100644 --- a/internal/services/order_service/internal/orders/features/getting_order_by_id/v1/queries/get_order_by_id_handler.go +++ b/internal/services/order_service/internal/orders/features/getting_order_by_id/v1/queries/get_order_by_id_handler.go @@ -9,6 +9,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/contracts/repositories" dtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/dtos" @@ -46,7 +47,7 @@ func (q *GetOrderByIdHandler) Handle( // get order by order-read id order, err := q.orderMongoRepository.GetOrderById(ctx, query.Id) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, @@ -62,7 +63,7 @@ func (q *GetOrderByIdHandler) Handle( // get order by order-write id order, err = q.orderMongoRepository.GetOrderByOrderId(ctx, query.Id) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, @@ -77,7 +78,7 @@ func (q *GetOrderByIdHandler) Handle( orderDto, err := mapper.Map[*dtosV1.OrderReadDto](order) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, diff --git a/internal/services/order_service/internal/orders/features/getting_orders/v1/queries/get_orders_handler.go b/internal/services/order_service/internal/orders/features/getting_orders/v1/queries/get_orders_handler.go index eeffb60d..c5d41d83 100644 --- a/internal/services/order_service/internal/orders/features/getting_orders/v1/queries/get_orders_handler.go +++ b/internal/services/order_service/internal/orders/features/getting_orders/v1/queries/get_orders_handler.go @@ -7,6 +7,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + utils2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/contracts/repositories" dtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/dtos/v1" @@ -41,7 +42,7 @@ func (c *GetOrdersHandler) Handle( products, err := c.mongoOrderReadRepository.GetAllOrders(ctx, query.ListQuery) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, @@ -52,7 +53,7 @@ func (c *GetOrdersHandler) Handle( listResultDto, err := utils.ListResultToListResultDto[*dtosV1.OrderReadDto](products) if err != nil { - return nil, tracing.TraceErrFromSpan( + return nil, utils2.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, diff --git a/internal/services/order_service/internal/orders/projections/mongo_order_projection.go b/internal/services/order_service/internal/orders/projections/mongo_order_projection.go index e79ac59b..559d4612 100644 --- a/internal/services/order_service/internal/orders/projections/mongo_order_projection.go +++ b/internal/services/order_service/internal/orders/projections/mongo_order_projection.go @@ -12,6 +12,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/contracts/repositories" dtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/dtos/v1" createOrderDomainEventsV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/creating_order/v1/events/domain_events" @@ -82,7 +83,7 @@ func (m *mongoOrderProjection) onOrderCreated( ) _, err = m.mongoOrderRepository.CreateOrder(ctx, orderRead) if err != nil { - return tracing.TraceErrFromSpan( + return utils.TraceErrFromSpan( span, errors.WrapIf( err, @@ -93,7 +94,7 @@ func (m *mongoOrderProjection) onOrderCreated( orderReadDto, err := mapper.Map[*dtosV1.OrderReadDto](orderRead) if err != nil { - return tracing.TraceErrFromSpan( + return utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, @@ -106,7 +107,7 @@ func (m *mongoOrderProjection) onOrderCreated( err = m.rabbitmqProducer.PublishMessage(ctx, orderCreatedEvent, nil) if err != nil { - return tracing.TraceErrFromSpan( + return utils.TraceErrFromSpan( span, customErrors.NewApplicationErrorWrap( err, diff --git a/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go b/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go index 6bf878de..54fcd8e9 100644 --- a/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go +++ b/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go @@ -2,20 +2,44 @@ package infrastructure import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/pipelines" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" + pipelines2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/pipelines" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" + tracingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/pipelines" + + "github.com/mehdihadeli/go-mediatr" ) type InfrastructureConfigurator struct { contracts.Application } -func NewInfrastructureConfigurator(app contracts.Application) *InfrastructureConfigurator { +func NewInfrastructureConfigurator( + app contracts.Application, +) *InfrastructureConfigurator { return &InfrastructureConfigurator{ Application: app, } } func (ic *InfrastructureConfigurator) ConfigInfrastructures() { - ic.ResolveFunc(func() error { - return nil - }) + ic.ResolveFunc( + func(logger logger.Logger, tracer tracing.AppTracer, metrics metrics.AppMetrics) error { + err := mediatr.RegisterRequestPipelineBehaviors( + pipelines.NewLoggingPipeline(logger), + tracingpipelines.NewTracingPipeline( + tracer, + tracingpipelines.WithLogger(logger), + ), + pipelines2.NewMetricsPipeline( + metrics, + pipelines2.WithLogger(logger), + ), + ) + + return err + }, + ) } diff --git a/internal/services/order_service/internal/shared/grpc/order_grpc_service_server.go b/internal/services/order_service/internal/shared/grpc/order_grpc_service_server.go index b779042d..da09de3d 100644 --- a/internal/services/order_service/internal/shared/grpc/order_grpc_service_server.go +++ b/internal/services/order_service/internal/shared/grpc/order_grpc_service_server.go @@ -7,8 +7,8 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" attribute2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + utils2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" dtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/dtos/v1" createOrderCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/creating_order/v1/commands" @@ -166,7 +166,7 @@ func (o OrderGrpcServiceServer) GetOrderByID( err, "[OrderGrpcServiceServer_GetOrderByID.Map] error in mapping order", ) - return nil, tracing.TraceErrFromContext(ctx, err) + return nil, utils2.TraceStatusFromContext(ctx, err) } return &grpcOrderService.GetOrderByIDRes{Order: order}, nil From f23b53b600fe8c7d267162082a160249bcbf269f Mon Sep 17 00:00:00 2001 From: mehdihadeli Date: Fri, 6 Oct 2023 19:11:36 +0330 Subject: [PATCH 05/15] build: :bricks: some docker compose changes --- ...cker-compose.infrastructure-collector.yaml | 5 +- .../docker-compose.infrastructure.yaml | 6 +- .../docker-compose/monitoring/grafana.yaml | 30 ++++----- .../docker-compose/otel-collector-config.yaml | 66 ------------------- 4 files changed, 15 insertions(+), 92 deletions(-) delete mode 100644 deployments/docker-compose/otel-collector-config.yaml diff --git a/deployments/docker-compose/docker-compose.infrastructure-collector.yaml b/deployments/docker-compose/docker-compose.infrastructure-collector.yaml index e5879a7c..841eeb9a 100644 --- a/deployments/docker-compose/docker-compose.infrastructure-collector.yaml +++ b/deployments/docker-compose/docker-compose.infrastructure-collector.yaml @@ -109,9 +109,6 @@ services: ports: - ${GRAFANA_HOST_PORT:-3000}:${GRAFANA_PORT:-3000} environment: - - GF_AUTH_ANONYMOUS_ENABLED=true - - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin - - GF_AUTH_DISABLE_LOGIN_FORM=true - GF_FEATURE_TOGGLES_ENABLE=traceqlEditor healthcheck: interval: 5s @@ -132,7 +129,7 @@ services: # https://grafana.com/docs/tempo/latest/operations/architecture/ tempo: image: grafana/tempo:latest - command: [ "-search.enabled=true", "-config.file=/etc/tempo.yaml" ] + command: ["-config.file=/etc/tempo.yaml" ] volumes: - ./otelcollector/tempo.yaml:/etc/tempo.yaml - ./tempo-data:/tmp/tempo diff --git a/deployments/docker-compose/docker-compose.infrastructure.yaml b/deployments/docker-compose/docker-compose.infrastructure.yaml index a3f6b378..2c7144e3 100644 --- a/deployments/docker-compose/docker-compose.infrastructure.yaml +++ b/deployments/docker-compose/docker-compose.infrastructure.yaml @@ -68,9 +68,6 @@ services: ports: - ${GRAFANA_HOST_PORT:-3000}:${GRAFANA_PORT:-3000} environment: - - GF_AUTH_ANONYMOUS_ENABLED=true - - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin - - GF_AUTH_DISABLE_LOGIN_FORM=true - GF_FEATURE_TOGGLES_ENABLE=traceqlEditor healthcheck: interval: 5s @@ -91,10 +88,9 @@ services: # https://grafana.com/docs/tempo/latest/operations/architecture/ tempo: image: grafana/tempo:latest - command: [ "-search.enabled=true", "-config.file=/etc/tempo.yaml" ] + command: ["-config.file=/etc/tempo.yaml" ] volumes: - ./otelcollector/tempo.yaml:/etc/tempo.yaml - - ./tempo-data:/tmp/tempo ports: - "3200:3200" # tempo UI - "4322:4317" # otlp grpc diff --git a/deployments/docker-compose/monitoring/grafana.yaml b/deployments/docker-compose/monitoring/grafana.yaml index 0290ca02..e1001431 100644 --- a/deployments/docker-compose/monitoring/grafana.yaml +++ b/deployments/docker-compose/monitoring/grafana.yaml @@ -19,23 +19,19 @@ datasources: access: proxy editable: true -# # showing Tempo as one of dashboard tabs -# # https://github.com/grafana/tempo/blob/main/example/docker-compose/shared/grafana-datasources.yaml#L16 -# - name: Tempo -# type: tempo -# access: proxy -# orgId: 1 -# url: http://tempo:3200 -# basicAuth: false -# isDefault: true -# version: 1 -# editable: false -# apiVersion: 1 -# uid: tempo -# jsonData: -# httpMethod: GET -# serviceMap: -# datasourceUid: prometheus + # showing Tempo as one of dashboard tabs + # https://github.com/grafana/tempo/blob/main/example/docker-compose/shared/grafana-datasources.yaml#L16 + - name: Tempo + type: tempo + access: proxy + orgId: 1 + url: http://tempo:3200 + basicAuth: false + isDefault: false + version: 1 + editable: false + apiVersion: 1 + uid: tempo # # showing Loki as one of dashboard tabs # - name: loki diff --git a/deployments/docker-compose/otel-collector-config.yaml b/deployments/docker-compose/otel-collector-config.yaml deleted file mode 100644 index 63315cfc..00000000 --- a/deployments/docker-compose/otel-collector-config.yaml +++ /dev/null @@ -1,66 +0,0 @@ -receivers: - otlp: - protocols: - grpc: - -exporters: - prometheus: - endpoint: "0.0.0.0:8889" - const_labels: - label1: value1 - - logging: - - zipkin: - endpoint: "http://zipkin:9411/api/v2/spans" - format: proto - - jaeger: - endpoint: jaeger:14250 - tls: - insecure: true - - elasticsearch: - endpoints: - - "http://elastic_search:9200" - -# #https://www.elastic.co/guide/en/apm/guide/current/open-telemetry-direct.html#open-telemetry-proxy-apm -# otlp/elastic: -# # Elastic APM server https endpoint without the "https://" prefix -# endpoint: "http://elastic-apm-server:8200" -# headers: -# # Elastic APM Server secret token -# Authorization: "Bearer ${ELASTIC_APM_SECRET_TOKEN}" - -# # https://uptrace:dev/opentelemetry/prometheus-metrics:html#prometheus-receiver -# otlp/uptrace: -# endpoint: otlp.uptrace.dev:4317 -# headers: -# # Copy your project DSN here -# uptrace-dsn: 'https://@uptrace.dev/ - -processors: - batch: - -extensions: - health_check: - pprof: - endpoint: :1888 - zpages: - endpoint: :55679 - -service: - extensions: [pprof, zpages, health_check] - pipelines: - traces: - receivers: [otlp] - processors: [batch] - exporters: [logging, zipkin, jaeger] # otlp/elastic - metrics: - receivers: [otlp] - processors: [batch] - exporters: [logging, prometheus] # otlp/uptrace, otlp/elastic - logs: - receivers: [otlp] - processors: [batch] - exporters: [logging, elasticsearch] # otlp/elastic From d79cd1724dbda2baede56a1089c16ac19822f891 Mon Sep 17 00:00:00 2001 From: mehdihadeli Date: Sat, 14 Oct 2023 18:47:46 +0330 Subject: [PATCH 06/15] refactor: :recycle: refactor tracing and monitoring --- internal/pkg/go.mod | 1 + internal/pkg/go.sum | 2 + internal/pkg/grpc/handlers/otel/handler.go | 5 +- internal/pkg/http/custom_echo/echo_server.go | 2 + .../middlewares/ip_ratelimit/config.go | 41 ++++++++++ .../middlewares/ip_ratelimit/ip_ratelimit.go | 77 +++++++++++++++++++ .../middlewares/otel_metrics/metric.go | 38 +++++---- .../otel/tracing/consumer/consumer.go | 2 +- .../otel/tracing/producer/producer.go | 63 +++++++++++---- internal/pkg/messaging/otel/tracing/utils.go | 38 --------- .../config/config.development.json | 4 + .../repositories/mongo_product_repository.go | 65 +++++++++------- .../repositories/redis_product_repository.go | 60 +++++++++------ .../v1/commands/create_product_handler.go | 34 +++----- .../product_created_consumer.go | 36 ++++----- .../v1/commands/delete_product_handler.go | 65 ++++++---------- .../product_deleted_consumer.go | 35 +++------ .../endpoints/get_product_by_id_endpoint.go | 26 ++----- .../product_updated_consumer.go | 14 ++-- .../v1/endpoints/create_product_endpoint.go | 3 +- .../v1/endpoints/delete_product_endpoint.go | 1 - .../endpoints/get_product_by_id_endpoint.go | 1 - .../v1/endpoints/get_products_endpoint.go | 1 - .../v1/endpoints/search_products_endpoint.go | 1 - .../v1/endpoints/update_product_endpoint.go | 6 +- .../shared/contracts/catalogs_metrics.go | 6 -- scripts/format.sh | 3 +- 27 files changed, 359 insertions(+), 271 deletions(-) create mode 100644 internal/pkg/http/custom_echo/middlewares/ip_ratelimit/config.go create mode 100644 internal/pkg/http/custom_echo/middlewares/ip_ratelimit/ip_ratelimit.go delete mode 100644 internal/pkg/messaging/otel/tracing/utils.go diff --git a/internal/pkg/go.mod b/internal/pkg/go.mod index 08ad8de4..7e74380c 100644 --- a/internal/pkg/go.mod +++ b/internal/pkg/go.mod @@ -54,6 +54,7 @@ require ( github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.25.0 github.com/testcontainers/testcontainers-go/modules/postgres v0.25.0 + github.com/ulule/limiter/v3 v3.11.2 github.com/uptrace/bun v1.1.16 github.com/uptrace/bun/dialect/pgdialect v1.1.16 github.com/uptrace/bun/driver/pgdriver v1.1.16 diff --git a/internal/pkg/go.sum b/internal/pkg/go.sum index 00114664..b86ed166 100644 --- a/internal/pkg/go.sum +++ b/internal/pkg/go.sum @@ -644,6 +644,8 @@ github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+F github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= +github.com/ulule/limiter/v3 v3.11.2 h1:P4yOrxoEMJbOTfRJR2OzjL90oflzYPPmWg+dvwN2tHA= +github.com/ulule/limiter/v3 v3.11.2/go.mod h1:QG5GnFOCV+k7lrL5Y8kgEeeflPH3+Cviqlqa8SVSQxI= github.com/uptrace/bun v1.1.16 h1:cn9cgEMFwcyYRsQLfxCRMUxyK1WaHwOVrR3TvzEFZ/A= github.com/uptrace/bun v1.1.16/go.mod h1:7HnsMRRvpLFUcquJxp22JO8PsWKpFQO/gNXqqsuGWg8= github.com/uptrace/bun/dialect/pgdialect v1.1.16 h1:eUPZ+YCJ69BA+W1X1ZmpOJSkv1oYtinr0zCXf7zCo5g= diff --git a/internal/pkg/grpc/handlers/otel/handler.go b/internal/pkg/grpc/handlers/otel/handler.go index caded99c..71c14707 100644 --- a/internal/pkg/grpc/handlers/otel/handler.go +++ b/internal/pkg/grpc/handlers/otel/handler.go @@ -2,7 +2,6 @@ package otel import ( "context" - "fmt" "strings" "time" @@ -126,7 +125,7 @@ func newHandler(spanKind trace.SpanKind, options []Option) (handler, error) { } rpcTotalFailed, err := meter.Int64Counter( - fmt.Sprintf("%s_error_grpc_requests_total", c.serviceName), + prefix+".rpc_error_total", metric.WithDescription("The total number of error grpc requests"), metric.WithUnit("count"), ) @@ -135,7 +134,7 @@ func newHandler(spanKind trace.SpanKind, options []Option) (handler, error) { } rpcTotalSuccess, err := meter.Int64Counter( - fmt.Sprintf("%s_success_grpc_requests_total", c.serviceName), + prefix+".rpc_success_total", metric.WithDescription("The total number of success grpc requests"), metric.WithUnit("count"), ) diff --git a/internal/pkg/http/custom_echo/echo_server.go b/internal/pkg/http/custom_echo/echo_server.go index 741df138..384878d3 100644 --- a/internal/pkg/http/custom_echo/echo_server.go +++ b/internal/pkg/http/custom_echo/echo_server.go @@ -9,6 +9,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" hadnlers "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/hadnlers" + ipratelimit "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/middlewares/ip_ratelimit" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/middlewares/log" otelMetrics "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/middlewares/otel_metrics" oteltracing "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/middlewares/otel_tracing" @@ -134,6 +135,7 @@ func (s *echoHttpServer) SetupDefaultMiddlewares() { otelMetrics.WithSkipper(skipper)), ) s.echo.Use(middleware.BodyLimit(constants.BodyLimit)) + s.echo.Use(ipratelimit.IPRateLimit()) s.echo.Use(middleware.RequestID()) s.echo.Use(middleware.GzipWithConfig(middleware.GzipConfig{ Level: constants.GzipLevel, diff --git a/internal/pkg/http/custom_echo/middlewares/ip_ratelimit/config.go b/internal/pkg/http/custom_echo/middlewares/ip_ratelimit/config.go new file mode 100644 index 00000000..ddc919a8 --- /dev/null +++ b/internal/pkg/http/custom_echo/middlewares/ip_ratelimit/config.go @@ -0,0 +1,41 @@ +package ipratelimit + +import ( + "time" +) + +type config struct { + period time.Duration + limit int64 +} + +var defualtConfig = config{ + period: 1 * time.Hour, + limit: 1000, +} + +type Option interface { + apply(*config) +} + +type optionFunc func(*config) + +func (o optionFunc) apply(c *config) { + o(c) +} + +func WithPeriod(d time.Duration) Option { + return optionFunc(func(cfg *config) { + if cfg.period != 0 { + cfg.period = d + } + }) +} + +func WithLimit(v int64) Option { + return optionFunc(func(cfg *config) { + if cfg.limit != 0 { + cfg.limit = v + } + }) +} diff --git a/internal/pkg/http/custom_echo/middlewares/ip_ratelimit/ip_ratelimit.go b/internal/pkg/http/custom_echo/middlewares/ip_ratelimit/ip_ratelimit.go new file mode 100644 index 00000000..4d069f60 --- /dev/null +++ b/internal/pkg/http/custom_echo/middlewares/ip_ratelimit/ip_ratelimit.go @@ -0,0 +1,77 @@ +package ipratelimit + +import ( + "log" + "net/http" + "strconv" + + "github.com/labstack/echo/v4" + "github.com/ulule/limiter/v3" + "github.com/ulule/limiter/v3/drivers/store/memory" +) + +// ref: https://github.com/ulule/limiter-examples/blob/master/echo/main.go + +func IPRateLimit(opts ...Option) echo.MiddlewareFunc { + config := defualtConfig + + for _, opt := range opts { + opt.apply(&config) + } + + rate := limiter.Rate{ + Period: config.period, + Limit: config.limit, + } + + var ( + ipRateLimiter *limiter.Limiter + store limiter.Store + ) + + store = memory.NewStore() + ipRateLimiter = limiter.New(store, rate) + + // 2. Return middleware handler + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) (err error) { + ip := c.RealIP() + limiterCtx, err := ipRateLimiter.Get(c.Request().Context(), ip) + if err != nil { + log.Printf( + "IPRateLimit - ipRateLimiter.Get - err: %v, %s on %s", + err, + ip, + c.Request().URL, + ) + return c.JSON(http.StatusInternalServerError, echo.Map{ + "success": false, + "message": err, + }) + } + + h := c.Response().Header() + h.Set("X-RateLimit-Limit", strconv.FormatInt(limiterCtx.Limit, 10)) + h.Set( + "X-RateLimit-Remaining", + strconv.FormatInt(limiterCtx.Remaining, 10), + ) + h.Set("X-RateLimit-Reset", strconv.FormatInt(limiterCtx.Reset, 10)) + + if limiterCtx.Reached { + log.Printf( + "Too Many Requests from %s on %s", + ip, + c.Request().URL, + ) + return c.JSON(http.StatusTooManyRequests, echo.Map{ + "success": false, + "message": "Too Many Requests on " + c.Request().URL.String(), + }) + } + + // log.Printf("%s request continue", c.RealIP()) + return next(c) + } + } +} diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/metric.go b/internal/pkg/http/custom_echo/middlewares/otel_metrics/metric.go index 3ed99210..3cf76957 100644 --- a/internal/pkg/http/custom_echo/middlewares/otel_metrics/metric.go +++ b/internal/pkg/http/custom_echo/middlewares/otel_metrics/metric.go @@ -74,14 +74,16 @@ func (h *HTTPMetricsRecorder) namespacedValue(v string) string { } func (h *HTTPMetricsRecorder) register() error { - errorCounter, err := h.meter.Float64Counter( //nolint:errcheck - fmt.Sprintf("%s_error_http_requests_total", h.cfg.serviceName), + // https://opentelemetry.io/docs/specs/otel/metrics/semantic_conventions/http-metrics/#http-server + errorCounter, err := h.meter.Float64Counter( + "http.server.total_error_request", + metric.WithUnit("count"), metric.WithDescription("The total number of error http requests"), ) if err != nil { return fmt.Errorf( "meter %s cannot set; %w", - fmt.Sprintf("%s_error_http_requests_total", h.cfg.serviceName), + "http.server.total_error_request", err, ) } @@ -89,13 +91,14 @@ func (h *HTTPMetricsRecorder) register() error { h.errorCounter = errorCounter successCounter, err := h.meter.Float64Counter( - fmt.Sprintf("%s_success_http_requests_total", h.cfg.serviceName), + "http.server.total_success_request", + metric.WithUnit("count"), metric.WithDescription("The total number of success http requests"), ) if err != nil { return fmt.Errorf( "meter %s cannot set; %w", - fmt.Sprintf("%s_success_http_requests_total", h.cfg.serviceName), + "http.server.total_success_request", err, ) } @@ -104,13 +107,14 @@ func (h *HTTPMetricsRecorder) register() error { if h.cfg.enableTotalMetric { reqTotal, err := h.meter.Int64Counter( - h.namespacedValue("http_requests_total"), + h.namespacedValue("http.server.total_request"), + metric.WithUnit("count"), metric.WithDescription("The total number of requests"), ) if err != nil { return fmt.Errorf( "meter %s cannot set; %w", - "http_requests_total", + "http.server.total_request", err, ) } @@ -120,7 +124,8 @@ func (h *HTTPMetricsRecorder) register() error { if h.cfg.enableDurMetric { reqDuration, err := h.meter.Float64Histogram( - h.namespacedValue("request_duration_seconds"), + h.namespacedValue("http.server.duration"), + metric.WithUnit("s"), // Specify the unit as "seconds" metric.WithDescription( "The total duration of a request in seconds", ), @@ -128,7 +133,7 @@ func (h *HTTPMetricsRecorder) register() error { if err != nil { return fmt.Errorf( "meter %s cannot set; %w", - "request_duration_seconds", + "http.server.duration", err, ) } @@ -138,13 +143,14 @@ func (h *HTTPMetricsRecorder) register() error { if h.cfg.enableInFlightMetric { reqInFlight, err := h.meter.Int64UpDownCounter( - h.namespacedValue("requests_inflight_total"), + h.namespacedValue("http.server.request_inflight_total"), + metric.WithUnit("count"), metric.WithDescription("The current number of in-flight requests"), ) if err != nil { return fmt.Errorf( "meter %s cannot set; %w", - "requests_inflight_total", + "http.server.request_inflight_total", err, ) } @@ -153,13 +159,14 @@ func (h *HTTPMetricsRecorder) register() error { } resSize, err := h.meter.Int64Histogram( - h.namespacedValue("response_size"), + h.namespacedValue("http.server.response.size"), + metric.WithUnit("bytes"), metric.WithDescription("The HTTP response sizes in bytes."), ) if err != nil { return fmt.Errorf( "meter %s cannot set; %w", - "response_size", + "http.server.response.size", err, ) } @@ -167,13 +174,14 @@ func (h *HTTPMetricsRecorder) register() error { h.resSize = resSize reqSize, err := h.meter.Int64Histogram( - h.namespacedValue("request_size"), + h.namespacedValue("http.server.request.size"), + metric.WithUnit("bytes"), metric.WithDescription("The HTTP request sizes in bytes."), ) if err != nil { return fmt.Errorf( "meter %s cannot set; %w", - "request_size", + "http.server.request.size", err, ) } diff --git a/internal/pkg/messaging/otel/tracing/consumer/consumer.go b/internal/pkg/messaging/otel/tracing/consumer/consumer.go index f3a573da..6452a03b 100644 --- a/internal/pkg/messaging/otel/tracing/consumer/consumer.go +++ b/internal/pkg/messaging/otel/tracing/consumer/consumer.go @@ -62,7 +62,7 @@ func FinishConsumerSpan(span trace.Span, err error) error { if err != nil { span.AddEvent(fmt.Sprintf("failed to consume message '%s' from the broker", messageName)) - _ = messageTracing.TraceMessagingErrFromSpan(span, err) + _ = utils.TraceErrStatusFromSpan(span, err) } span.SetAttributes( diff --git a/internal/pkg/messaging/otel/tracing/producer/producer.go b/internal/pkg/messaging/otel/tracing/producer/producer.go index 1533dc08..23bc6eb3 100644 --- a/internal/pkg/messaging/otel/tracing/producer/producer.go +++ b/internal/pkg/messaging/otel/tracing/producer/producer.go @@ -49,7 +49,12 @@ func StartProducerSpan( fmt.Sprintf("%s %s", producerTracingOptions.Destination, "send"), opts...) - span.AddEvent(fmt.Sprintf("start publishing message '%s' to the broker", messageHeader.GetMessageName(*meta))) + span.AddEvent( + fmt.Sprintf( + "start publishing message '%s' to the broker", + messageHeader.GetMessageName(*meta), + ), + ) // Injects current span context, so consumers can use it to propagate span. // injects the tracing from the context into the header map @@ -60,18 +65,33 @@ func StartProducerSpan( } func FinishProducerSpan(span trace.Span, err error) error { - messageName := utils.GetSpanAttribute(span, messageTracing.MessageName).Value.AsString() + messageName := utils.GetSpanAttribute( + span, + messageTracing.MessageName, + ).Value.AsString() if err != nil { - span.AddEvent(fmt.Sprintf("failed to publsih message '%s' to the broker", messageName)) - _ = messageTracing.TraceMessagingErrFromSpan(span, err) + span.AddEvent( + fmt.Sprintf( + "failed to publsih message '%s' to the broker", + messageName, + ), + ) + _ = utils.TraceErrStatusFromSpan(span, err) } span.SetAttributes( - attribute.Key(constants.TraceId).String(span.SpanContext().TraceID().String()), - attribute.Key(constants.SpanId).String(span.SpanContext().SpanID().String()), // current span id + attribute.Key(constants.TraceId). + String(span.SpanContext().TraceID().String()), + attribute.Key(constants.SpanId). + String(span.SpanContext().SpanID().String()), // current span id ) - span.AddEvent(fmt.Sprintf("message '%s' published to the broker succesfully", messageName)) + span.AddEvent( + fmt.Sprintf( + "message '%s' published to the broker succesfully", + messageName, + ), + ) span.End() return err @@ -90,17 +110,22 @@ func getTraceOptions( attrs := []attribute.KeyValue{ semconv.MessageIDKey.String(message.GeMessageId()), semconv.MessagingMessageConversationID(correlationId), - attribute.Key(messageTracing.MessageType).String(message.GetEventTypeName()), - attribute.Key(messageTracing.MessageName).String(messageHeader.GetMessageName(*meta)), + attribute.Key(messageTracing.MessageType). + String(message.GetEventTypeName()), + attribute.Key(messageTracing.MessageName). + String(messageHeader.GetMessageName(*meta)), attribute.Key(messageTracing.Payload).String(payload), attribute.String(messageTracing.Headers, meta.ToJson()), attribute.Key(constants.Timestamp).Int64(time.Now().UnixMilli()), semconv.MessagingDestinationName(producerTracingOptions.Destination), - semconv.MessagingSystemKey.String(producerTracingOptions.MessagingSystem), + semconv.MessagingSystemKey.String( + producerTracingOptions.MessagingSystem, + ), semconv.MessagingOperationKey.String("send"), } - if producerTracingOptions.OtherAttributes != nil && len(producerTracingOptions.OtherAttributes) > 0 { + if producerTracingOptions.OtherAttributes != nil && + len(producerTracingOptions.OtherAttributes) > 0 { attrs = append(attrs, producerTracingOptions.OtherAttributes...) } @@ -111,11 +136,21 @@ func getTraceOptions( return opts } -func addAfterBaggage(ctx context.Context, message types.IMessage, meta *metadata.Metadata) context.Context { +func addAfterBaggage( + ctx context.Context, + message types.IMessage, + meta *metadata.Metadata, +) context.Context { correlationId := messageHeader.GetCorrelationId(*meta) - correlationIdBag, _ := baggage.NewMember(string(semconv.MessagingMessageConversationIDKey), correlationId) - messageIdBag, _ := baggage.NewMember(string(semconv.MessageIDKey), message.GeMessageId()) + correlationIdBag, _ := baggage.NewMember( + string(semconv.MessagingMessageConversationIDKey), + correlationId, + ) + messageIdBag, _ := baggage.NewMember( + string(semconv.MessageIDKey), + message.GeMessageId(), + ) b, _ := baggage.New(correlationIdBag, messageIdBag) ctx = baggage.ContextWithBaggage(ctx, b) diff --git a/internal/pkg/messaging/otel/tracing/utils.go b/internal/pkg/messaging/otel/tracing/utils.go deleted file mode 100644 index 91c17097..00000000 --- a/internal/pkg/messaging/otel/tracing/utils.go +++ /dev/null @@ -1,38 +0,0 @@ -package tracing - -import ( - "context" - - errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/codes" - "go.opentelemetry.io/otel/trace" -) - -// TraceMessagingErrFromSpan setting span with status error with error message -func TraceMessagingErrFromSpan(span trace.Span, err error) error { - if err != nil { - stackTraceError := errorUtils.ErrorsWithStack(err) - span.SetStatus(codes.Error, "") - span.SetAttributes(attribute.String(MessagingErrorMessage, stackTraceError)) - span.RecordError(err) - } - - return err -} - -func TraceMessagingErrFromContext(ctx context.Context, err error) error { - // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors - span := trace.SpanFromContext(ctx) - defer span.End() - - if err != nil { - stackTraceError := errorUtils.ErrorsWithStack(err) - span.SetStatus(codes.Error, "") - span.SetAttributes(attribute.String(MessagingErrorMessage, stackTraceError)) - span.RecordError(err) - } - - return err -} diff --git a/internal/services/catalog_read_service/config/config.development.json b/internal/services/catalog_read_service/config/config.development.json index 6353dc65..05a58d3b 100644 --- a/internal/services/catalog_read_service/config/config.development.json +++ b/internal/services/catalog_read_service/config/config.development.json @@ -66,6 +66,10 @@ "otlpEndpoint": "localhost:4320", "enabled": true }, + "tempoExporterOptions": { + "otlpEndpoint": "localhost:4322", + "enabled": true + }, "zipkinExporterOptions": { "url": "http://localhost:9411/api/v2/spans" }, diff --git a/internal/services/catalog_read_service/internal/products/data/repositories/mongo_product_repository.go b/internal/services/catalog_read_service/internal/products/data/repositories/mongo_product_repository.go index e0399656..ea5c9dff 100644 --- a/internal/services/catalog_read_service/internal/products/data/repositories/mongo_product_repository.go +++ b/internal/services/catalog_read_service/internal/products/data/repositories/mongo_product_repository.go @@ -49,7 +49,11 @@ func NewMongoProductRepository( mongoOptions.Database, productCollection, ) - return &mongoProductRepository{log: log, mongoGenericRepository: mongoRepo, tracer: tracer} + return &mongoProductRepository{ + log: log, + mongoGenericRepository: mongoRepo, + tracer: tracer, + } } func (p *mongoProductRepository) GetAllProducts( @@ -62,17 +66,17 @@ func (p *mongoProductRepository) GetAllProducts( // https://www.mongodb.com/docs/drivers/go/current/fundamentals/crud/read-operations/query-document/ result, err := p.mongoGenericRepository.GetAll(ctx, listQuery) if err != nil { - return nil, utils2.TraceErrFromSpan( + return nil, utils2.TraceErrStatusFromSpan( span, errors.WrapIf( err, - "[mongoProductRepository_GetAllProducts.Paginate] error in the paginate", + "error in the paginate", ), ) } p.log.Infow( - "[mongoProductRepository.GetAllProducts] products loaded", + "products loaded", logger.Fields{"ProductsResult": result}, ) @@ -92,18 +96,18 @@ func (p *mongoProductRepository) SearchProducts( result, err := p.mongoGenericRepository.Search(ctx, searchText, listQuery) if err != nil { - return nil, utils2.TraceErrFromSpan( + return nil, utils2.TraceErrStatusFromSpan( span, errors.WrapIf( err, - "[mongoProductRepository_SearchProducts.Paginate] error in the paginate", + "error in the paginate", ), ) } p.log.Infow( fmt.Sprintf( - "[mongoProductRepository.SearchProducts] products loaded for search term '%s'", + "products loaded for search term '%s'", searchText, ), logger.Fields{"ProductsResult": result}, @@ -129,12 +133,12 @@ func (p *mongoProductRepository) GetProductById( product, err := p.mongoGenericRepository.GetById(ctx, id) if err != nil { - return nil, utils2.TraceErrFromSpan( + return nil, utils2.TraceStatusFromSpan( span, errors.WrapIf( err, fmt.Sprintf( - "[mongoProductRepository_GetProductById.FindOne] can't find the product with id %s into the database.", + "can't find the product with id %s into the database.", uuid, ), ), @@ -144,7 +148,7 @@ func (p *mongoProductRepository) GetProductById( span.SetAttributes(attribute.Object("Product", product)) p.log.Infow( - fmt.Sprintf("[mongoProductRepository.GetProductById] product with id %s laoded", uuid), + fmt.Sprintf("product with id %s laoded", uuid), logger.Fields{"Product": product, "Id": uuid}, ) @@ -156,7 +160,10 @@ func (p *mongoProductRepository) GetProductByProductId( uuid string, ) (*models.Product, error) { productId := uuid - ctx, span := p.tracer.Start(ctx, "mongoProductRepository.GetProductByProductId") + ctx, span := p.tracer.Start( + ctx, + "mongoProductRepository.GetProductByProductId", + ) span.SetAttributes(attribute2.String("ProductId", productId)) defer span.End() @@ -165,12 +172,12 @@ func (p *mongoProductRepository) GetProductByProductId( map[string]interface{}{"productId": uuid}, ) if err != nil { - return nil, utils2.TraceErrFromSpan( + return nil, utils2.TraceStatusFromSpan( span, errors.WrapIf( err, fmt.Sprintf( - "[mongoProductRepository_GetProductById.FindOne] can't find the product with productId %s into the database.", + "can't find the product with productId %s into the database.", uuid, ), ), @@ -181,7 +188,7 @@ func (p *mongoProductRepository) GetProductByProductId( p.log.Infow( fmt.Sprintf( - "[mongoProductRepository.GetProductById] product with productId %s laoded", + "product with productId %s laoded", productId, ), logger.Fields{"Product": product, "ProductId": uuid}, @@ -199,11 +206,11 @@ func (p *mongoProductRepository) CreateProduct( err := p.mongoGenericRepository.Add(ctx, product) if err != nil { - return nil, utils2.TraceErrFromSpan( + return nil, utils2.TraceErrStatusFromSpan( span, errors.WrapIf( err, - "[mongoProductRepository_CreateProduct.InsertOne] error in the inserting product into the database.", + "error in the inserting product into the database.", ), ) } @@ -212,7 +219,7 @@ func (p *mongoProductRepository) CreateProduct( p.log.Infow( fmt.Sprintf( - "[mongoProductRepository.CreateProduct] product with id '%s' created", + "product with id '%s' created", product.ProductId, ), logger.Fields{"Product": product, "Id": product.ProductId}, @@ -231,12 +238,12 @@ func (p *mongoProductRepository) UpdateProduct( err := p.mongoGenericRepository.Update(ctx, updateProduct) // https://www.mongodb.com/docs/manual/reference/method/db.collection.findOneAndUpdate/ if err != nil { - return nil, utils2.TraceErrFromSpan( + return nil, utils2.TraceErrStatusFromSpan( span, errors.WrapIf( err, fmt.Sprintf( - "[mongoProductRepository_UpdateProduct.FindOneAndUpdate] error in updating product with id %s into the database.", + "error in updating product with id %s into the database.", updateProduct.ProductId, ), ), @@ -246,7 +253,7 @@ func (p *mongoProductRepository) UpdateProduct( span.SetAttributes(attribute.Object("Product", updateProduct)) p.log.Infow( fmt.Sprintf( - "[mongoProductRepository.UpdateProduct] product with id '%s' updated", + "product with id '%s' updated", updateProduct.ProductId, ), logger.Fields{"Product": updateProduct, "Id": updateProduct.ProductId}, @@ -255,7 +262,10 @@ func (p *mongoProductRepository) UpdateProduct( return updateProduct, nil } -func (p *mongoProductRepository) DeleteProductByID(ctx context.Context, uuid string) error { +func (p *mongoProductRepository) DeleteProductByID( + ctx context.Context, + uuid string, +) error { ctx, span := p.tracer.Start(ctx, "mongoProductRepository.DeleteProductByID") span.SetAttributes(attribute2.String("Id", uuid)) defer span.End() @@ -267,14 +277,17 @@ func (p *mongoProductRepository) DeleteProductByID(ctx context.Context, uuid str err = p.mongoGenericRepository.Delete(ctx, id) if err != nil { - return utils2.TraceErrFromSpan(span, errors.WrapIf(err, fmt.Sprintf( - "[mongoProductRepository_DeleteProductByID.FindOneAndDelete] error in deleting product with id %s from the database.", - uuid, - ))) + return utils2.TraceErrStatusFromSpan( + span, + errors.WrapIf(err, fmt.Sprintf( + "error in deleting product with id %s from the database.", + uuid, + )), + ) } p.log.Infow( - fmt.Sprintf("[mongoProductRepository.DeleteProductByID] product with id %s deleted", uuid), + fmt.Sprintf("product with id %s deleted", uuid), logger.Fields{"Product": uuid}, ) diff --git a/internal/services/catalog_read_service/internal/products/data/repositories/redis_product_repository.go b/internal/services/catalog_read_service/internal/products/data/repositories/redis_product_repository.go index c35f6954..3387dd3b 100644 --- a/internal/services/catalog_read_service/internal/products/data/repositories/redis_product_repository.go +++ b/internal/services/catalog_read_service/internal/products/data/repositories/redis_product_repository.go @@ -32,7 +32,11 @@ func NewRedisProductRepository( redisClient redis.UniversalClient, tracer tracing.AppTracer, ) data.ProductCacheRepository { - return &redisProductRepository{log: log, redisClient: redisClient, tracer: tracer} + return &redisProductRepository{ + log: log, + redisClient: redisClient, + tracer: tracer, + } } func (r *redisProductRepository) PutProduct( @@ -41,28 +45,30 @@ func (r *redisProductRepository) PutProduct( product *models.Product, ) error { ctx, span := r.tracer.Start(ctx, "redisRepository.PutProduct") - span.SetAttributes(attribute2.String("PrefixKey", r.getRedisProductPrefixKey())) + span.SetAttributes( + attribute2.String("PrefixKey", r.getRedisProductPrefixKey()), + ) span.SetAttributes(attribute2.String("Key", key)) defer span.End() productBytes, err := json.Marshal(product) if err != nil { - return utils.TraceErrFromSpan( + return utils.TraceErrStatusFromSpan( span, errors.WrapIf( err, - "[redisProductRepository_PutProduct.Marshal] error marshalling product", + "error marshalling product", ), ) } if err := r.redisClient.HSetNX(ctx, r.getRedisProductPrefixKey(), key, productBytes).Err(); err != nil { - return utils.TraceErrFromSpan( + return utils.TraceErrStatusFromSpan( span, errors.WrapIf( err, fmt.Sprintf( - "[redisProductRepository_PutProduct.HSetNX] error in updating product with key %s", + "error in updating product with key %s", key, ), ), @@ -73,7 +79,7 @@ func (r *redisProductRepository) PutProduct( r.log.Infow( fmt.Sprintf( - "[redisProductRepository.PutProduct] product with key '%s', prefix '%s' updated successfully", + "product with key '%s', prefix '%s' updated successfully", key, r.getRedisProductPrefixKey(), ), @@ -93,22 +99,25 @@ func (r *redisProductRepository) GetProductById( key string, ) (*models.Product, error) { ctx, span := r.tracer.Start(ctx, "redisRepository.GetProductById") - span.SetAttributes(attribute2.String("PrefixKey", r.getRedisProductPrefixKey())) + span.SetAttributes( + attribute2.String("PrefixKey", r.getRedisProductPrefixKey()), + ) span.SetAttributes(attribute2.String("Key", key)) defer span.End() - productBytes, err := r.redisClient.HGet(ctx, r.getRedisProductPrefixKey(), key).Bytes() + productBytes, err := r.redisClient.HGet(ctx, r.getRedisProductPrefixKey(), key). + Bytes() if err != nil { if errors.Is(err, redis.Nil) { return nil, nil } - return nil, utils.TraceErrFromSpan( + return nil, utils.TraceErrStatusFromSpan( span, errors.WrapIf( err, fmt.Sprintf( - "[redisProductRepository_GetProduct.HGet] error in getting product with Key %s from database", + "error in getting product with Key %s from database", key, ), ), @@ -117,14 +126,14 @@ func (r *redisProductRepository) GetProductById( var product models.Product if err := json.Unmarshal(productBytes, &product); err != nil { - return nil, utils.TraceErrFromSpan(span, err) + return nil, utils.TraceErrStatusFromSpan(span, err) } span.SetAttributes(attribute.Object("Product", product)) r.log.Infow( fmt.Sprintf( - "[redisProductRepository.GetProductById] product with with key '%s', prefix '%s' laoded", + "product with with key '%s', prefix '%s' laoded", key, r.getRedisProductPrefixKey(), ), @@ -139,19 +148,24 @@ func (r *redisProductRepository) GetProductById( return &product, nil } -func (r *redisProductRepository) DeleteProduct(ctx context.Context, key string) error { +func (r *redisProductRepository) DeleteProduct( + ctx context.Context, + key string, +) error { ctx, span := r.tracer.Start(ctx, "redisRepository.DeleteProduct") - span.SetAttributes(attribute2.String("PrefixKey", r.getRedisProductPrefixKey())) + span.SetAttributes( + attribute2.String("PrefixKey", r.getRedisProductPrefixKey()), + ) span.SetAttributes(attribute2.String("Key", key)) defer span.End() if err := r.redisClient.HDel(ctx, r.getRedisProductPrefixKey(), key).Err(); err != nil { - return utils.TraceErrFromSpan( + return utils.TraceErrStatusFromSpan( span, errors.WrapIf( err, fmt.Sprintf( - "[redisProductRepository_DeleteProduct.HDel] error in deleting product with key %s", + "error in deleting product with key %s", key, ), ), @@ -160,7 +174,7 @@ func (r *redisProductRepository) DeleteProduct(ctx context.Context, key string) r.log.Infow( fmt.Sprintf( - "[redisProductRepository.DeleteProduct] product with key %s, prefix: %s deleted successfully", + "product with key %s, prefix: %s deleted successfully", key, r.getRedisProductPrefixKey(), ), @@ -172,21 +186,23 @@ func (r *redisProductRepository) DeleteProduct(ctx context.Context, key string) func (r *redisProductRepository) DeleteAllProducts(ctx context.Context) error { ctx, span := r.tracer.Start(ctx, "redisRepository.DeleteAllProducts") - span.SetAttributes(attribute2.String("PrefixKey", r.getRedisProductPrefixKey())) + span.SetAttributes( + attribute2.String("PrefixKey", r.getRedisProductPrefixKey()), + ) defer span.End() if err := r.redisClient.Del(ctx, r.getRedisProductPrefixKey()).Err(); err != nil { - return utils.TraceErrFromSpan( + return utils.TraceErrStatusFromSpan( span, errors.WrapIf( err, - "[redisProductRepository_DeleteAllProducts.Del] error in deleting all products", + "error in deleting all products", ), ) } r.log.Infow( - "[redisProductRepository.DeleteAllProducts] all products deleted", + "all products deleted", logger.Fields{"PrefixKey": r.getRedisProductPrefixKey()}, ) diff --git a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/commands/create_product_handler.go b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/commands/create_product_handler.go index b9eb6365..b6c1d1ed 100644 --- a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/commands/create_product_handler.go +++ b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/commands/create_product_handler.go @@ -7,13 +7,9 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/models" - - attribute2 "go.opentelemetry.io/otel/attribute" ) type CreateProductHandler struct { @@ -41,12 +37,6 @@ func (c *CreateProductHandler) Handle( ctx context.Context, command *CreateProduct, ) (*dtos.CreateProductResponseDto, error) { - ctx, span := c.tracer.Start(ctx, "CreateProductHandler.Handle") - span.SetAttributes(attribute2.String("ProductId", command.ProductId)) - span.SetAttributes(attribute.Object("Command", command)) - - defer span.End() - product := &models.Product{ Id: command.Id, // we generate id ourselves because auto generate mongo string id column with type _id is not an uuid ProductId: command.ProductId, @@ -58,31 +48,27 @@ func (c *CreateProductHandler) Handle( createdProduct, err := c.mongoRepository.CreateProduct(ctx, product) if err != nil { - return nil, utils.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[CreateProductHandler_Handle.CreateProduct] error in creating product in the mongo repository", - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in creating product in the mongo repository", ) } err = c.redisRepository.PutProduct(ctx, createdProduct.Id, createdProduct) if err != nil { - return nil, utils.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[CreateProductHandler_Handle.PutProduct] error in creating product in the redis repository", - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in creating product in the redis repository", ) } response := &dtos.CreateProductResponseDto{Id: createdProduct.Id} - span.SetAttributes(attribute.Object("CreateProductResponseDto", response)) c.log.Infow( - fmt.Sprintf("[CreateProductHandler.Handle] product with id: {%s} created", product.Id), + fmt.Sprintf( + "product with id: {%s} created", + product.Id, + ), logger.Fields{"ProductId": command.ProductId, "Id": product.Id}, ) diff --git a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integration_events/external_events/product_created_consumer.go b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integration_events/external_events/product_created_consumer.go index f8a07529..1c4e3582 100644 --- a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integration_events/external_events/product_created_consumer.go +++ b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integration_events/external_events/product_created_consumer.go @@ -7,10 +7,8 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - messageTracing "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/commands" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/dtos" @@ -30,7 +28,11 @@ func NewProductCreatedConsumer( validator *validator.Validate, tracer tracing.AppTracer, ) consumer.ConsumerHandler { - return &productCreatedConsumer{logger: logger, validator: validator, tracer: tracer} + return &productCreatedConsumer{ + logger: logger, + validator: validator, + tracer: tracer, + } } func (c *productCreatedConsumer) Handle( @@ -42,10 +44,6 @@ func (c *productCreatedConsumer) Handle( return errors.New("error in casting message to ProductCreatedV1") } - ctx, span := c.tracer.Start(ctx, "productCreatedConsumer.Handle") - span.SetAttributes(attribute.Object("Message", consumeContext.Message())) - defer span.End() - command, err := commands.NewCreateProduct( product.ProductId, product.Name, @@ -56,30 +54,22 @@ func (c *productCreatedConsumer) Handle( if err != nil { validationErr := customErrors.NewValidationErrorWrap( err, - "[productCreatedConsumer_Handle.StructCtx] command validation failed", - ) - c.logger.Errorf( - fmt.Sprintf( - "[productCreatedConsumer_Handle.StructCtx] err: {%v}", - messageTracing.TraceMessagingErrFromSpan(span, validationErr), - ), + "command validation failed", ) - return err + return validationErr } - _, err = mediatr.Send[*commands.CreateProduct, *dtos.CreateProductResponseDto](ctx, command) + _, err = mediatr.Send[*commands.CreateProduct, *dtos.CreateProductResponseDto]( + ctx, + command, + ) if err != nil { - err = errors.WithMessage( + return errors.WithMessage( err, - "[productCreatedConsumer_Handle.Send] error in sending CreateProduct", - ) - c.logger.Errorw( fmt.Sprintf( - "[productCreatedConsumer_Handle.Send] id: {%s}, err: {%v}", + "error in sending CreateProduct with id: {%s}", command.ProductId, - messageTracing.TraceMessagingErrFromSpan(span, err), ), - logger.Fields{"Id": command.ProductId}, ) } c.logger.Info("Product consumer handled.") diff --git a/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/commands/delete_product_handler.go b/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/commands/delete_product_handler.go index adc70314..68a8711b 100644 --- a/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/commands/delete_product_handler.go +++ b/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/commands/delete_product_handler.go @@ -7,12 +7,9 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" "github.com/mehdihadeli/go-mediatr" - attribute2 "go.opentelemetry.io/otel/attribute" ) type DeleteProductCommand struct { @@ -40,63 +37,49 @@ func (c *DeleteProductCommand) Handle( ctx context.Context, command *DeleteProduct, ) (*mediatr.Unit, error) { - ctx, span := c.tracer.Start(ctx, "DeleteProductCommand.Handle") - span.SetAttributes(attribute2.String("ProductId", command.ProductId.String())) - span.SetAttributes(attribute.Object("Command", command)) - product, err := c.mongoRepository.GetProductByProductId(ctx, command.ProductId.String()) - - defer span.End() - + product, err := c.mongoRepository.GetProductByProductId( + ctx, + command.ProductId.String(), + ) if err != nil { - return nil, utils.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - fmt.Sprintf( - "[DeleteProductHandler_Handle.GetProductById] error in fetching product with productId %s in the mongo repository", - command.ProductId, - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + fmt.Sprintf( + "error in fetching product with productId %s in the mongo repository", + command.ProductId, ), ) } if product == nil { - return nil, utils.TraceErrFromSpan( - span, - customErrors.NewNotFoundErrorWrap( - err, - fmt.Sprintf( - "[DeleteProductHandler_Handle.GetProductById] product with productId %s not found", - command.ProductId, - ), + return nil, customErrors.NewNotFoundErrorWrap( + err, + fmt.Sprintf( + "product with productId %s not found", + command.ProductId, ), ) } if err := c.mongoRepository.DeleteProductByID(ctx, product.Id); err != nil { - return nil, utils.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[DeleteProductHandler_Handle.DeleteProductByID] error in deleting product in the mongo repository", - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in deleting product in the mongo repository", ) } - c.log.Infof("(product deleted) id: {%s}", product.Id) - err = c.redisRepository.DeleteProduct(ctx, product.Id) if err != nil { - return nil, utils.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[DeleteProductHandler_Handle.DeleteProduct] error in deleting product in the redis repository", - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in deleting product in the redis repository", ) } c.log.Infow( - fmt.Sprintf("[DeleteProductCommand.Handle] product with id: {%s} deleted", product.Id), + fmt.Sprintf( + "product with id: {%s} deleted", + product.Id, + ), logger.Fields{"ProductId": command.ProductId, "Id": product.Id}, ) diff --git a/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted_consumer.go b/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted_consumer.go index cfc220a5..829d8baa 100644 --- a/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted_consumer.go +++ b/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted_consumer.go @@ -2,15 +2,12 @@ package externalEvents import ( "context" - "fmt" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - messageTracing "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/deleting_products/v1/commands" "emperror.dev/errors" @@ -30,7 +27,11 @@ func NewProductDeletedConsumer( validator *validator.Validate, tracer tracing.AppTracer, ) consumer.ConsumerHandler { - return &productDeletedConsumer{logger: logger, validator: validator, tracer: tracer} + return &productDeletedConsumer{ + logger: logger, + validator: validator, + tracer: tracer, + } } func (c *productDeletedConsumer) Handle( @@ -42,43 +43,29 @@ func (c *productDeletedConsumer) Handle( return errors.New("error in casting message to ProductDeletedV1") } - ctx, span := c.tracer.Start(ctx, "productDeletedConsumer.Handle") - span.SetAttributes(attribute.Object("Message", consumeContext.Message())) - defer span.End() - productUUID, err := uuid.FromString(message.ProductId) if err != nil { badRequestErr := customErrors.NewBadRequestErrorWrap( err, - "[productDeletedConsumer_Handle.uuid.FromString] error in the converting uuid", - ) - c.logger.Errorf( - fmt.Sprintf( - "[productDeletedConsumer_Handle.uuid.FromString] err: %v", - messageTracing.TraceMessagingErrFromSpan(span, badRequestErr), - ), + "error in the converting uuid", ) - return err + return badRequestErr } command, err := commands.NewDeleteProduct(productUUID) if err != nil { validationErr := customErrors.NewValidationErrorWrap( err, - "[productDeletedConsumer_Handle.StructCtx] command validation failed", - ) - c.logger.Errorf( - fmt.Sprintf( - "[productDeletedConsumer_Consume.StructCtx] err: {%v}", - messageTracing.TraceMessagingErrFromSpan(span, validationErr), - ), + "command validation failed", ) - return err + return validationErr } _, err = mediatr.Send[*commands.DeleteProduct, *mediatr.Unit](ctx, command) + c.logger.Info("productDeletedConsumer executed successfully.") + return err } diff --git a/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/endpoints/get_product_by_id_endpoint.go b/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/endpoints/get_product_by_id_endpoint.go index 87788619..cd78bb03 100644 --- a/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/endpoints/get_product_by_id_endpoint.go +++ b/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/endpoints/get_product_by_id_endpoint.go @@ -1,11 +1,9 @@ package endpoints import ( - "fmt" "net/http" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/params" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/dtos" @@ -44,17 +42,14 @@ func (ep *getProductByIdEndpoint) MapEndpoint() { func (ep *getProductByIdEndpoint) handler() echo.HandlerFunc { return func(c echo.Context) error { ctx := c.Request().Context() - ep.CatalogsMetrics.GetProductByIdHttpRequests.Add(ctx, 1) request := &dtos.GetProductByIdRequestDto{} if err := c.Bind(request); err != nil { badRequestErr := customErrors.NewBadRequestErrorWrap( err, - "[getProductByIdEndpoint_handler.Bind] error in the binding request", - ) - ep.Logger.Errorf( - fmt.Sprintf("[getProductByIdEndpoint_handler.Bind] err: %v", badRequestErr), + "error in the binding request", ) + return badRequestErr } @@ -62,9 +57,9 @@ func (ep *getProductByIdEndpoint) handler() echo.HandlerFunc { if err != nil { validationErr := customErrors.NewValidationErrorWrap( err, - "[getProductByIdEndpoint_handler.StructCtx] query validation failed", + "query validation failed", ) - ep.Logger.Errorf("[getProductByIdEndpoint_handler.StructCtx] err: {%v}", validationErr) + return validationErr } @@ -73,19 +68,10 @@ func (ep *getProductByIdEndpoint) handler() echo.HandlerFunc { query, ) if err != nil { - err = errors.WithMessage( + return errors.WithMessage( err, - "[getProductByIdEndpoint_handler.Send] error in sending GetProductById", - ) - ep.Logger.Errorw( - fmt.Sprintf( - "[getProductByIdEndpoint_handler.Send] id: {%s}, err: {%v}", - query.Id, - err, - ), - logger.Fields{"ProductId": query.Id}, + "error in sending GetProductById", ) - return err } return c.JSON(http.StatusOK, queryResult) diff --git a/internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated_consumer.go b/internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated_consumer.go index 4a92ac93..2837cd73 100644 --- a/internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated_consumer.go +++ b/internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated_consumer.go @@ -7,10 +7,10 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - messageTracing "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/updating_products/v1/commands" "emperror.dev/errors" @@ -30,7 +30,11 @@ func NewProductUpdatedConsumer( validator *validator.Validate, tracer tracing.AppTracer, ) consumer.ConsumerHandler { - return &productUpdatedConsumer{logger: logger, validator: validator, tracer: tracer} + return &productUpdatedConsumer{ + logger: logger, + validator: validator, + tracer: tracer, + } } func (c *productUpdatedConsumer) Handle( @@ -56,7 +60,7 @@ func (c *productUpdatedConsumer) Handle( c.logger.Errorf( fmt.Sprintf( "[updateProductConsumer_Consume.uuid.FromString] err: %v", - messageTracing.TraceMessagingErrFromSpan(span, badRequestErr), + utils.TraceErrStatusFromSpan(span, badRequestErr), ), ) return err @@ -76,7 +80,7 @@ func (c *productUpdatedConsumer) Handle( c.logger.Errorf( fmt.Sprintf( "[updateProductConsumer_Consume.StructCtx] err: {%v}", - messageTracing.TraceMessagingErrFromSpan(span, validationErr), + utils.TraceErrStatusFromSpan(span, validationErr), ), ) return err @@ -92,7 +96,7 @@ func (c *productUpdatedConsumer) Handle( fmt.Sprintf( "[updateProductConsumer_Consume.Send] id: {%s}, err: {%v}", command.ProductId, - messageTracing.TraceMessagingErrFromSpan(span, err), + utils.TraceErrStatusFromSpan(span, err), ), logger.Fields{"Id": command.ProductId}, ) diff --git a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/endpoints/create_product_endpoint.go b/internal/services/catalog_write_service/internal/products/features/creating_product/v1/endpoints/create_product_endpoint.go index 07fadef3..9097c2b6 100644 --- a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/endpoints/create_product_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/creating_product/v1/endpoints/create_product_endpoint.go @@ -39,8 +39,6 @@ func (ep *createProductEndpoint) handler() echo.HandlerFunc { return func(c echo.Context) error { ctx := c.Request().Context() - ep.CatalogsMetrics.CreateProductHttpRequests.Add(ctx, 1) - request := &dtos.CreateProductRequestDto{} if err := c.Bind(request); err != nil { badRequestErr := customErrors.NewBadRequestErrorWrap( @@ -61,6 +59,7 @@ func (ep *createProductEndpoint) handler() echo.HandlerFunc { err, "command validation failed", ) + return validationErr } diff --git a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/endpoints/delete_product_endpoint.go b/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/endpoints/delete_product_endpoint.go index e8cd7ecf..8de61923 100644 --- a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/endpoints/delete_product_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/endpoints/delete_product_endpoint.go @@ -40,7 +40,6 @@ func (ep *deleteProductEndpoint) MapEndpoint() { func (ep *deleteProductEndpoint) handler() echo.HandlerFunc { return func(c echo.Context) error { ctx := c.Request().Context() - ep.CatalogsMetrics.DeleteProductHttpRequests.Add(ctx, 1) request := &dtos.DeleteProductRequestDto{} if err := c.Bind(request); err != nil { diff --git a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/endpoints/get_product_by_id_endpoint.go b/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/endpoints/get_product_by_id_endpoint.go index bee89310..bb0e3fa1 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/endpoints/get_product_by_id_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/endpoints/get_product_by_id_endpoint.go @@ -40,7 +40,6 @@ func (ep *getProductByIdEndpoint) MapEndpoint() { func (ep *getProductByIdEndpoint) handler() echo.HandlerFunc { return func(c echo.Context) error { ctx := c.Request().Context() - ep.CatalogsMetrics.GetProductByIdHttpRequests.Add(ctx, 1) request := &dtos.GetProductByIdRequestDto{} if err := c.Bind(request); err != nil { diff --git a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go index 0df6e389..35928fb5 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go @@ -41,7 +41,6 @@ func (ep *getProductsEndpoint) MapEndpoint() { func (ep *getProductsEndpoint) handler() echo.HandlerFunc { return func(c echo.Context) error { ctx := c.Request().Context() - ep.CatalogsMetrics.GetProductsHttpRequests.Add(ctx, 1) listQuery, err := utils.GetListQueryFromCtx(c) if err != nil { diff --git a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/endpoints/search_products_endpoint.go b/internal/services/catalog_write_service/internal/products/features/searching_product/v1/endpoints/search_products_endpoint.go index 9ddfbec2..0be06f35 100644 --- a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/endpoints/search_products_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/searching_product/v1/endpoints/search_products_endpoint.go @@ -41,7 +41,6 @@ func (ep *searchProductsEndpoint) MapEndpoint() { func (ep *searchProductsEndpoint) handler() echo.HandlerFunc { return func(c echo.Context) error { ctx := c.Request().Context() - ep.CatalogsMetrics.SearchProductHttpRequests.Add(ctx, 1) listQuery, err := utils.GetListQueryFromCtx(c) if err != nil { diff --git a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/endpoints/update_product_endpoint.go b/internal/services/catalog_write_service/internal/products/features/updating_product/v1/endpoints/update_product_endpoint.go index 1a6dff7d..74d1fe36 100644 --- a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/endpoints/update_product_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/updating_product/v1/endpoints/update_product_endpoint.go @@ -41,7 +41,6 @@ func (ep *updateProductEndpoint) MapEndpoint() { func (ep *updateProductEndpoint) handler() echo.HandlerFunc { return func(c echo.Context) error { ctx := c.Request().Context() - ep.CatalogsMetrics.UpdateProductHttpRequests.Add(ctx, 1) request := &dtos.UpdateProductRequestDto{} if err := c.Bind(request); err != nil { @@ -68,7 +67,10 @@ func (ep *updateProductEndpoint) handler() echo.HandlerFunc { return validationErr } - _, err = mediatr.Send[*commands.UpdateProduct, *mediatr.Unit](ctx, command) + _, err = mediatr.Send[*commands.UpdateProduct, *mediatr.Unit]( + ctx, + command, + ) if err != nil { return errors.WithMessage( err, diff --git a/internal/services/catalog_write_service/internal/shared/contracts/catalogs_metrics.go b/internal/services/catalog_write_service/internal/shared/contracts/catalogs_metrics.go index f6701e6a..7db30b63 100644 --- a/internal/services/catalog_write_service/internal/shared/contracts/catalogs_metrics.go +++ b/internal/services/catalog_write_service/internal/shared/contracts/catalogs_metrics.go @@ -10,12 +10,6 @@ type CatalogsMetrics struct { DeleteProductGrpcRequests metric.Float64Counter GetProductByIdGrpcRequests metric.Float64Counter SearchProductGrpcRequests metric.Float64Counter - CreateProductHttpRequests metric.Float64Counter - UpdateProductHttpRequests metric.Float64Counter - DeleteProductHttpRequests metric.Float64Counter - GetProductByIdHttpRequests metric.Float64Counter - GetProductsHttpRequests metric.Float64Counter - SearchProductHttpRequests metric.Float64Counter SuccessRabbitMQMessages metric.Float64Counter ErrorRabbitMQMessages metric.Float64Counter CreateProductRabbitMQMessages metric.Float64Counter diff --git a/scripts/format.sh b/scripts/format.sh index 49bd3dce..6e1ae880 100644 --- a/scripts/format.sh +++ b/scripts/format.sh @@ -26,9 +26,10 @@ golines -m 120 -w --ignore-generated . # https://github.com/incu6us/goimports-reviser # https://github.com/incu6us/goimports-reviser/issues/118 # https://github.com/incu6us/goimports-reviser/issues/88 +# https://github.com/incu6us/goimports-reviser/issues/104 # will do `gofmt` internally if we use -format # -rm-unused, -set-alias have some errors ---> goimports-reviser -rm-unused -set-alias -format -recursive ./... -# goimports-reviser -company-prefixes "github.com/mehdihadeli" -project-name "github.com/mehdihadeli/go-ecommerce-microservices" -imports-order "std,general,company,project" -recursive ./... +# goimports-reviser -company-prefixes "github.com/mehdihadeli" -project-name "github.com/mehdihadeli/go-ecommerce-microservices" -rm-unused -set-alias -imports-order "std,general,company,project,blanked,dotted" -recursive ./... gci write --skip-generated -s standard -s "prefix(github.com/mehdihadeli/go-ecommerce-microservices)" -s default -s blank -s dot --custom-order . From 08a5c179b74f8a6a1ad0bab543d61b0f896cab95 Mon Sep 17 00:00:00 2001 From: mehdihadeli Date: Thu, 23 Nov 2023 19:26:02 +0330 Subject: [PATCH 07/15] refactor: :recycle: some refactoring --- .gitignore | 2 + Makefile | 8 + ...nfig.development.json => config.test.json} | 8 +- internal/pkg/config/config_helper.go | 10 +- internal/pkg/config/configfx.go | 12 +- .../environment.go | 2 +- internal/pkg/core/cqrs/handler.go | 14 + internal/pkg/core/cqrs/helpers.go | 22 ++ internal/pkg/{ => core}/web/route/endpoint.go | 0 internal/pkg/{ => core}/web/route/helpers.go | 0 internal/pkg/elasticsearch/elastic_options.go | 4 +- .../config/eventstoredb_options.go | 4 +- internal/pkg/fxapp/application.go | 8 +- internal/pkg/fxapp/application_builder.go | 10 +- internal/pkg/fxapp/contracts/application.go | 4 +- .../fxapp/contracts/application_builder.go | 4 +- internal/pkg/fxapp/test/test_app_fx.go | 4 +- internal/pkg/fxapp/test/test_application.go | 8 +- .../fxapp/test/test_application_builder.go | 6 +- internal/pkg/go.mod | 2 +- internal/pkg/go.sum | 2 + internal/pkg/gorm_postgres/gorm_options.go | 4 +- internal/pkg/grpc/config/grpc_options.go | 4 +- .../custom_echo/config/echo_http_options.go | 4 +- .../middlewares/ip_ratelimit/ip_ratelimit.go | 2 + internal/pkg/logger/config/log_options.go | 4 +- internal/pkg/logger/logrous/logrous_logger.go | 6 +- internal/pkg/logger/zap/zap_logger.go | 6 +- .../messaging/pipeline/consumer_pipeline.go | 2 +- internal/pkg/migration/migration_options.go | 4 +- internal/pkg/mongodb/mongo_options.go | 4 +- .../metrics/{ => mediatr}/pipelines/config.go | 0 .../pipelines/mediator_metrics_pipeline.go} | 26 +- .../messaging/pipeline}/config.go | 0 .../pipeline/messaging_metrics_pipeline.go | 258 ++++++++++++++++++ internal/pkg/otel/metrics/metrics.go | 6 +- internal/pkg/otel/metrics/metrics_options.go | 4 +- .../otel/tracing/mediatr/pipelines/config.go | 43 +++ .../pipelines/mediator_tracing_pipeline.go} | 8 +- internal/pkg/otel/tracing/tracing.go | 6 +- internal/pkg/otel/tracing/tracing_options.go | 4 +- .../pkg/postgres_pgx/postgres_pgx_options.go | 4 +- .../postgres_sqlx/postgres_sqlx_options.go | 4 +- internal/pkg/rabbitmq/bus/rabbitmq-bus.go | 73 +++-- .../pkg/rabbitmq/bus/rabbitmq_bus_test.go | 2 +- .../pkg/rabbitmq/config/rabbitmq_options.go | 4 +- .../consumercontracts/consumer_factory.go | 17 ++ .../consumer/factory/consumer_factory.go | 51 ++++ .../rabbitmq/consumer/rabbitmq_consumer.go | 59 +++- .../consumer/rabbitmq_consumer_test.go | 142 +++++----- .../pkg/rabbitmq/producer/producer_factory.go | 46 ++++ .../producercontracts/producer_factory.go | 14 + .../rabbitmq/producer/rabbitmq_producer.go | 18 +- .../producer/rabbitmq_producer_test.go | 29 +- internal/pkg/rabbitmq/rabbitmq_fx.go | 15 +- .../testcontainer/rabbitmq_test_container.go | 95 +++++++ internal/pkg/redis/redis_options.go | 4 +- .../contracts/eventstoredb_container.go | 8 +- .../containers/contracts/gorm_container.go | 5 +- .../containers/contracts/mongo_container.go | 9 +- .../contracts/postgrespgx_container.go | 3 +- .../contracts/rabbitmq_container.go | 19 +- .../containers/contracts/redis_container.go | 9 +- .../dockertest/gorm/gorm_container.go | 30 +- .../dockertest/gorm/gorm_container_test.go | 28 +- .../containers/dockertest/gorm/gorm_fx.go | 14 + .../dockertest/mongo/mongo_container.go | 42 +-- .../dockertest/mongo/mongo_container_test.go | 27 +- .../containers/dockertest/mongo/mongo_fx.go | 15 + .../dockertest/rabbitmq/rabbitmq_container.go | 153 ++++++----- .../rabbitmq/rabbitmq_container_test.go | 64 +++-- .../dockertest/rabbitmq/rabbitmq_fx.go | 2 +- .../containers/gnomock/gorm/gorm_container.go | 4 +- .../eveentstoredb_container_test.go | 27 +- .../eventstoredb/eventstoredb_container.go | 4 +- .../eventstoredb/eventstoredb_fx.go | 4 +- .../testcontainer/gorm/gorm_container.go | 6 +- .../testcontainer/gorm/gorm_container_test.go | 23 +- .../containers/testcontainer/gorm/gorm_fx.go | 2 +- .../testcontainer/mongo/mongo_container.go | 56 ++-- .../mongo/mongo_container_test.go | 30 +- .../testcontainer/mongo/mongo_fx.go | 2 +- .../postgrespxg/postgrespgx_container.go | 4 +- .../postgrespxg/postgrespgx_fx.go | 2 +- .../rabbitmq/rabbitmq_container.go | 50 +--- .../rabbitmq/rabbitmq_container_test.go | 62 +++-- .../testcontainer/rabbitmq/rabbitmq_fx.go | 2 +- .../testcontainer/redis/redis_container.go | 45 +-- .../redis/redis_container_test.go | 27 +- .../testcontainer/redis/redis_fx.go | 2 +- internal/pkg/validation/validation.go | 5 + .../config/config.development.json | 3 - .../catalog_read_service/config/config.go | 4 +- .../config/config.test.json | 3 - internal/services/catalog_read_service/go.mod | 2 +- internal/services/catalog_read_service/go.sum | 2 + .../mediator/mediator_configurations.go | 6 +- .../products_module_configurator.go | 9 +- .../rabbitmq/rabbitmq_configuration.go | 2 +- .../v1/{commands => }/create_product.go | 2 +- .../{commands => }/create_product_handler.go | 2 +- .../externalevents}/product_created.go | 0 .../product_created_consumer.go | 6 +- .../endpoints/get_product_by_id_endpoint.go | 2 +- .../v1/queries/get_product_by_id_handler.go | 51 ++-- .../v1/endpoints/get_products_endpoint.go | 27 +- .../v1/queries/get_products_handler.go | 36 +-- .../v1/endpoints/search_products_endpoint.go | 31 +-- .../v1/queries/search_products_handler.go | 42 ++- .../v1/commands/update_product_handler.go | 62 ++--- .../internal/products/products_fx.go | 2 +- .../internal/shared/app/application.go | 4 +- .../shared/app/test/test_application.go | 4 +- .../infrastructure_configurator.go | 8 +- .../shared/contracts/catalogs_metrics.go | 6 - .../v1/commands/create_product_test.go | 6 +- .../v1/events/product_created_test.go | 2 +- .../cmd/migration/main.go | 4 +- .../config/app_options.go | 4 +- .../config/config.development.json | 3 - .../config/config.test.json | 3 - .../services/catalog_write_service/go.mod | 9 +- .../services/catalog_write_service/go.sum | 91 +----- .../configurations/endpoints/endpoints.go | 13 + .../mappings/mapping_profile.go | 2 +- .../configurations/mediator/mediator.go | 14 + .../mediatr/mediator_configurations.go | 73 ----- .../products_module_configurator.go | 67 +++-- .../rabbitmq/rabbitmq_configurations.go | 11 +- .../{data => }/catalog_unit_of_work.go | 2 +- .../contracts/{data => }/catalogs_context.go | 2 +- .../params/product_endpoints_param.go | 13 - .../{data => }/product_repository.go | 2 +- .../repositories/pg_product_repository.go | 2 +- .../products/data/uow/catalog_context.go | 2 +- .../data/uow/catalogs_unit_of_work.go | 10 +- .../v1/fxparams/product_handler_params.go | 20 ++ .../v1/fxparams}/product_route_params.go | 2 +- .../products/{dto => dtos}/v1/product_dto.go | 2 +- .../v1/commands/create_product_handler.go | 110 -------- .../v1}/create_product.go | 3 +- .../v1}/create_product_endpoint.go | 19 +- .../v1/create_product_handler.go | 116 ++++++++ .../v1/dtos/create_product_request_dto.go | 0 .../v1/dtos/create_product_response_dto.go | 0 .../v1/events/domainevents}/.gitkeep | 0 .../integrationevents}/product_created.go | 4 +- .../v1/{commands => }/delete_product.go | 2 +- .../delete_product_endpoint.go | 15 +- .../{commands => }/delete_product_handler.go | 47 ++-- .../product_deleted.go | 0 .../v1/dtos/get_product_by_id_response_dto.go | 2 +- .../v1/{queries => }/get_product_by_id.go | 7 +- .../get_product_by_id_endpoint.go | 15 +- .../get_product_by_id_handler.go | 40 +-- .../v1/dtos/get_products_response_dto.go | 2 +- .../v1/{queries => }/get_products.go | 2 +- .../{endpoints => }/get_products_endpoint.go | 15 +- .../v1/get_products_handler.go | 52 ++++ .../v1/queries/get_products_handler.go | 47 ---- .../v1/dtos/search_products_response_dto.go | 2 +- .../v1/{queries => }/search_products.go | 2 +- .../search_products_endpoint.go | 15 +- .../{queries => }/search_products_handler.go | 39 +-- .../product_updated.go | 4 +- .../v1/{commands => }/update_product.go | 2 +- .../update_product_endpoint.go | 15 +- .../{commands => }/update_product_handler.go | 52 ++-- .../internal/products/products_fx.go | 59 +++- .../internal/shared/app/app.go | 12 +- .../internal/shared/app/application.go | 4 +- .../internal/shared/app/test/test_app.go | 27 +- .../shared/app/test/test_application.go | 4 +- .../catalogs/catalogs_configurator.go | 12 +- .../configurations/catalogs/catalogs_fx.go | 108 +++----- .../infrastructure_configurator.go | 8 +- .../grpc/product_grpc_service_server.go | 17 +- .../integration/integration_test_fixture.go | 10 +- .../unit_test/unit_test_fixture.go | 6 +- .../mocks/CatalogContext.go | 3 +- .../mocks/CatalogUnitOfWork.go | 3 +- .../mocks/CatalogUnitOfWorkActionFunc.go | 3 +- .../mocks/ProductRepository.go | 6 +- .../v1/create_product_test.go | 2 +- .../catalogs_unit_of_work_integration_test.go | 2 +- .../v1/create_product_test.go | 6 +- .../v1/delete_product_test.go | 18 +- .../v1/get_product_by_id_test.go | 2 +- .../getting_products/v1/get_products_test.go | 62 +++-- .../v1/update_product_test.go | 22 +- .../create_product_handler_unit_test.go | 2 +- .../v1/commands/create_product_unit_test.go | 2 +- .../delete_product_handler_unit_test.go | 14 +- .../v1/commands/delete_product_unit_test.go | 6 +- .../v1/queries/get_product_by_Id_unit_test.go | 2 +- .../get_product_by_id_handler_unit_test.go | 6 +- .../queries/get_products_handler_unit_test.go | 6 +- .../update_product_handler_unit_test.go | 14 +- .../v1/commands/update_product_unit_test.go | 10 +- .../unit/products/mappings_profile_test.go | 2 +- .../services/order_service/config/config.go | 4 +- internal/services/order_service/go.mod | 2 +- internal/services/order_service/go.sum | 2 + .../orders_module_configurator.go | 2 +- .../v1/endpoints/create_order_endpoint.go | 2 +- .../v1/endpoints/get_order_by_id_endpoint.go | 2 +- .../v1/endpoints/get_orders_endpoint.go | 2 +- .../internal/orders/orders_fx.go | 2 +- .../internal/shared/app/application.go | 4 +- .../shared/app/test/test_application.go | 4 +- .../infrastructure_configurator.go | 8 +- scripts/install-tools.sh | 2 + 212 files changed, 2162 insertions(+), 1529 deletions(-) rename internal/pkg/{config.development.json => config.test.json} (92%) rename internal/pkg/config/{environemnt => environment}/environment.go (99%) create mode 100644 internal/pkg/core/cqrs/handler.go create mode 100644 internal/pkg/core/cqrs/helpers.go rename internal/pkg/{ => core}/web/route/endpoint.go (100%) rename internal/pkg/{ => core}/web/route/helpers.go (100%) rename internal/pkg/otel/metrics/{ => mediatr}/pipelines/config.go (100%) rename internal/pkg/otel/metrics/{pipelines/metrics_pipeline.go => mediatr/pipelines/mediator_metrics_pipeline.go} (88%) rename internal/pkg/otel/{tracing/pipelines => metrics/messaging/pipeline}/config.go (100%) create mode 100644 internal/pkg/otel/metrics/messaging/pipeline/messaging_metrics_pipeline.go create mode 100644 internal/pkg/otel/tracing/mediatr/pipelines/config.go rename internal/pkg/otel/tracing/{pipelines/tracing_pipeline.go => mediatr/pipelines/mediator_tracing_pipeline.go} (95%) create mode 100644 internal/pkg/rabbitmq/consumer/consumercontracts/consumer_factory.go create mode 100644 internal/pkg/rabbitmq/consumer/factory/consumer_factory.go create mode 100644 internal/pkg/rabbitmq/producer/producer_factory.go create mode 100644 internal/pkg/rabbitmq/producer/producercontracts/producer_factory.go create mode 100644 internal/pkg/rabbitmq/test/testcontainer/rabbitmq_test_container.go create mode 100644 internal/pkg/test/containers/dockertest/gorm/gorm_fx.go create mode 100644 internal/pkg/test/containers/dockertest/mongo/mongo_fx.go create mode 100644 internal/pkg/validation/validation.go rename internal/services/catalog_read_service/internal/products/features/creating_product/v1/{commands => }/create_product.go (98%) rename internal/services/catalog_read_service/internal/products/features/creating_product/v1/{commands => }/create_product_handler.go (99%) rename internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/{integration_events/external_events => integrationevents/externalevents}/product_created.go (100%) rename internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/{integration_events/external_events => integrationevents/externalevents}/product_created_consumer.go (87%) create mode 100644 internal/services/catalog_write_service/internal/products/configurations/endpoints/endpoints.go create mode 100644 internal/services/catalog_write_service/internal/products/configurations/mediator/mediator.go delete mode 100644 internal/services/catalog_write_service/internal/products/configurations/mediatr/mediator_configurations.go rename internal/services/catalog_write_service/internal/products/contracts/{data => }/catalog_unit_of_work.go (94%) rename internal/services/catalog_write_service/internal/products/contracts/{data => }/catalogs_context.go (93%) delete mode 100644 internal/services/catalog_write_service/internal/products/contracts/params/product_endpoints_param.go rename internal/services/catalog_write_service/internal/products/contracts/{data => }/product_repository.go (97%) create mode 100644 internal/services/catalog_write_service/internal/products/dtos/v1/fxparams/product_handler_params.go rename internal/services/catalog_write_service/internal/products/{contracts/params => dtos/v1/fxparams}/product_route_params.go (96%) rename internal/services/catalog_write_service/internal/products/{dto => dtos}/v1/product_dto.go (95%) delete mode 100644 internal/services/catalog_write_service/internal/products/features/creating_product/v1/commands/create_product_handler.go rename internal/services/catalog_write_service/internal/products/features/{creating_product/v1/commands => creatingproduct/v1}/create_product.go (97%) rename internal/services/catalog_write_service/internal/products/features/{creating_product/v1/endpoints => creatingproduct/v1}/create_product_endpoint.go (73%) create mode 100644 internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_handler.go rename internal/services/catalog_write_service/internal/products/features/{creating_product => creatingproduct}/v1/dtos/create_product_request_dto.go (100%) rename internal/services/catalog_write_service/internal/products/features/{creating_product => creatingproduct}/v1/dtos/create_product_response_dto.go (100%) rename internal/services/catalog_write_service/internal/products/features/{creating_product/v1/events/domain_events => creatingproduct/v1/events/domainevents}/.gitkeep (100%) rename internal/services/catalog_write_service/internal/products/features/{creating_product/v1/events/integration_events => creatingproduct/v1/events/integrationevents}/product_created.go (84%) rename internal/services/catalog_write_service/internal/products/features/deleting_product/v1/{commands => }/delete_product.go (97%) rename internal/services/catalog_write_service/internal/products/features/deleting_product/v1/{endpoints => }/delete_product_endpoint.go (79%) rename internal/services/catalog_write_service/internal/products/features/deleting_product/v1/{commands => }/delete_product_handler.go (62%) rename internal/services/catalog_write_service/internal/products/features/deleting_product/v1/events/{integration_events => integrationevents}/product_deleted.go (100%) rename internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/{queries => }/get_product_by_id.go (80%) rename internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/{endpoints => }/get_product_by_id_endpoint.go (77%) rename internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/{queries => }/get_product_by_id_handler.go (63%) rename internal/services/catalog_write_service/internal/products/features/getting_products/v1/{queries => }/get_products.go (94%) rename internal/services/catalog_write_service/internal/products/features/getting_products/v1/{endpoints => }/get_products_endpoint.go (81%) create mode 100644 internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_handler.go delete mode 100644 internal/services/catalog_write_service/internal/products/features/getting_products/v1/queries/get_products_handler.go rename internal/services/catalog_write_service/internal/products/features/searching_product/v1/{queries => }/search_products.go (97%) rename internal/services/catalog_write_service/internal/products/features/searching_product/v1/{endpoints => }/search_products_endpoint.go (82%) rename internal/services/catalog_write_service/internal/products/features/searching_product/v1/{queries => }/search_products_handler.go (61%) rename internal/services/catalog_write_service/internal/products/features/updating_product/v1/events/{integration_events => integrationevents}/product_updated.go (84%) rename internal/services/catalog_write_service/internal/products/features/updating_product/v1/{commands => }/update_product.go (98%) rename internal/services/catalog_write_service/internal/products/features/updating_product/v1/{endpoints => }/update_product_endpoint.go (81%) rename internal/services/catalog_write_service/internal/products/features/updating_product/v1/{commands => }/update_product_handler.go (67%) diff --git a/.gitignore b/.gitignore index 2a5970e3..4935fdf5 100644 --- a/.gitignore +++ b/.gitignore @@ -186,3 +186,5 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* + +.cycle/ diff --git a/Makefile b/Makefile index 4be46890..eb60a135 100644 --- a/Makefile +++ b/Makefile @@ -115,6 +115,14 @@ atlas: @./scripts/atlas-migrate.sh -c gorm-sync -p "./internal/services/catalog_write_service" @./scripts/atlas-migrate.sh -c apply -p "./internal/services/catalog_write_service" -o "postgres://postgres:postgres@localhost:5432/catalogs_service?sslmode=disable" +.PHONY: cycle-check +cycle-check: + cd internal/services/catalog_write_service && goimportcycle -dot imports.dot dot -Tpng -o cycle/catalog_write_service.png imports.dot + cd internal/services/catalog_write_service && goimportcycle -dot imports.dot dot -Tpng -o cycle/catalog_write_service.png imports.dot + cd internal/services/catalog_read_service && goimportcycle -dot imports.dot dot -Tpng -o cycle/catalog_read_service.png imports.dot + cd internal/pkg && goimportcycle -dot imports.dot dot -Tpng -o cycle/pkg.png imports.dot + + #.PHONY: c4 #c4: # cd tools/c4 && go mod tidy && sh generate.sh diff --git a/internal/pkg/config.development.json b/internal/pkg/config.test.json similarity index 92% rename from internal/pkg/config.development.json rename to internal/pkg/config.test.json index eeff3f84..c2193758 100644 --- a/internal/pkg/config.development.json +++ b/internal/pkg/config.test.json @@ -70,7 +70,13 @@ "instrumentationName": "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test" }, "eventStoreDbOptions": { - "connectionString": "esdb://localhost:2113?tls=false" + "host": "localhost", + "httpPort": 2113, + "tcpPort": 1113, + "subscription": { + "subscriptionId": "orders-subscription", + "prefix": ["order-"] + } }, "migrationOptions": { "host": "localhost", diff --git a/internal/pkg/config/config_helper.go b/internal/pkg/config/config_helper.go index c46e4cf7..c96d56f0 100644 --- a/internal/pkg/config/config_helper.go +++ b/internal/pkg/config/config_helper.go @@ -6,7 +6,7 @@ import ( "path/filepath" "strings" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/constants" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" @@ -16,17 +16,17 @@ import ( "github.com/spf13/viper" ) -func BindConfig[T any](environments ...environemnt.Environment) (T, error) { +func BindConfig[T any](environments ...environment.Environment) (T, error) { return BindConfigKey[T]("", environments...) } func BindConfigKey[T any]( configKey string, - environments ...environemnt.Environment, + environments ...environment.Environment, ) (T, error) { var configPath string - environment := environemnt.Environment("") + environment := environment.Environment("") if len(environments) > 0 { environment = environments[0] } else { @@ -104,7 +104,7 @@ func BindConfigKey[T any]( // error: An error indicating any issues encountered during the search. func searchForConfigFileDir( rootDir string, - environment environemnt.Environment, + environment environment.Environment, ) (string, error) { var result string diff --git a/internal/pkg/config/configfx.go b/internal/pkg/config/configfx.go index b17ea753..d4b1eddd 100644 --- a/internal/pkg/config/configfx.go +++ b/internal/pkg/config/configfx.go @@ -1,7 +1,7 @@ package config import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "go.uber.org/fx" ) @@ -10,16 +10,16 @@ import ( // https://uber-go.github.io/fx/modules.html var Module = fx.Module( "configfx", - fx.Provide(func() environemnt.Environment { - return environemnt.ConfigAppEnv() + fx.Provide(func() environment.Environment { + return environment.ConfigAppEnv() }), ) -var ModuleFunc = func(e environemnt.Environment) fx.Option { +var ModuleFunc = func(e environment.Environment) fx.Option { return fx.Module( "configfx", - fx.Provide(func() environemnt.Environment { - return environemnt.ConfigAppEnv(e) + fx.Provide(func() environment.Environment { + return environment.ConfigAppEnv(e) }), ) } diff --git a/internal/pkg/config/environemnt/environment.go b/internal/pkg/config/environment/environment.go similarity index 99% rename from internal/pkg/config/environemnt/environment.go rename to internal/pkg/config/environment/environment.go index 7a0ededf..1e370bfa 100644 --- a/internal/pkg/config/environemnt/environment.go +++ b/internal/pkg/config/environment/environment.go @@ -1,4 +1,4 @@ -package environemnt +package environment import ( "log" diff --git a/internal/pkg/core/cqrs/handler.go b/internal/pkg/core/cqrs/handler.go new file mode 100644 index 00000000..39ee1a7e --- /dev/null +++ b/internal/pkg/core/cqrs/handler.go @@ -0,0 +1,14 @@ +package cqrs + +import "github.com/mehdihadeli/go-mediatr" + +// HandlerRegisterer for registering `RequestHandler` to mediatr registry, if handler implements this interface it will be registered automatically +type HandlerRegisterer interface { + RegisterHandler() error +} + +// RequestHandlerWithRegisterer for registering `RequestHandler` to mediatr registry and handling `RequestHandler` +type RequestHandlerWithRegisterer[TRequest any, TResponse any] interface { + HandlerRegisterer + mediatr.RequestHandler[TRequest, TResponse] +} diff --git a/internal/pkg/core/cqrs/helpers.go b/internal/pkg/core/cqrs/helpers.go new file mode 100644 index 00000000..2dbef123 --- /dev/null +++ b/internal/pkg/core/cqrs/helpers.go @@ -0,0 +1,22 @@ +package cqrs + +import ( + "fmt" + + "go.uber.org/fx" +) + +// when we register multiple handlers with output type `mediatr.RequestHandler` we get exception `type already provided`, so we should use tags annotation + +// AsHandler annotates the given constructor to state that +// it provides a handler to the "handlers" group. +func AsHandler(handler interface{}, handlerGroupName string) interface{} { + return fx.Annotate( + handler, + fx.As(new(HandlerRegisterer)), + fx.ResultTags(fmt.Sprintf( + `group:"%s"`, + handlerGroupName, + )), + ) +} diff --git a/internal/pkg/web/route/endpoint.go b/internal/pkg/core/web/route/endpoint.go similarity index 100% rename from internal/pkg/web/route/endpoint.go rename to internal/pkg/core/web/route/endpoint.go diff --git a/internal/pkg/web/route/helpers.go b/internal/pkg/core/web/route/helpers.go similarity index 100% rename from internal/pkg/web/route/helpers.go rename to internal/pkg/core/web/route/helpers.go diff --git a/internal/pkg/elasticsearch/elastic_options.go b/internal/pkg/elasticsearch/elastic_options.go index 6ccf3080..67e5f466 100644 --- a/internal/pkg/elasticsearch/elastic_options.go +++ b/internal/pkg/elasticsearch/elastic_options.go @@ -2,7 +2,7 @@ package elasticsearch import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" "github.com/iancoleman/strcase" @@ -14,6 +14,6 @@ type ElasticOptions struct { URL string `mapstructure:"url"` } -func provideConfig(environment environemnt.Environment) (*ElasticOptions, error) { +func provideConfig(environment environment.Environment) (*ElasticOptions, error) { return config.BindConfigKey[*ElasticOptions](optionName, environment) } diff --git a/internal/pkg/eventstroredb/config/eventstoredb_options.go b/internal/pkg/eventstroredb/config/eventstoredb_options.go index ca1e9a71..5046bbeb 100644 --- a/internal/pkg/eventstroredb/config/eventstoredb_options.go +++ b/internal/pkg/eventstroredb/config/eventstoredb_options.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" "github.com/iancoleman/strcase" @@ -49,7 +49,7 @@ type Subscription struct { SubscriptionId string `mapstructure:"subscriptionId" validate:"required"` } -func ProvideConfig(environment environemnt.Environment) (*EventStoreDbOptions, error) { +func ProvideConfig(environment environment.Environment) (*EventStoreDbOptions, error) { optionName := strcase.ToLowerCamel(typeMapper.GetTypeNameByT[EventStoreDbOptions]()) return config.BindConfigKey[*EventStoreDbOptions](optionName, environment) } diff --git a/internal/pkg/fxapp/application.go b/internal/pkg/fxapp/application.go index 8cdcc063..113f1c5d 100644 --- a/internal/pkg/fxapp/application.go +++ b/internal/pkg/fxapp/application.go @@ -3,7 +3,7 @@ package fxapp import ( "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" @@ -17,7 +17,7 @@ type application struct { options []fx.Option logger logger.Logger fxapp *fx.App - environment environemnt.Environment + environment environment.Environment } func NewApplication( @@ -25,7 +25,7 @@ func NewApplication( decorates []interface{}, options []fx.Option, logger logger.Logger, - env environemnt.Environment, + env environment.Environment, ) contracts.Application { return &application{ provides: providers, @@ -109,6 +109,6 @@ func (a *application) Logger() logger.Logger { return a.logger } -func (a *application) Environment() environemnt.Environment { +func (a *application) Environment() environment.Environment { return a.environment } diff --git a/internal/pkg/fxapp/application_builder.go b/internal/pkg/fxapp/application_builder.go index af0ca4c8..276247e0 100644 --- a/internal/pkg/fxapp/application_builder.go +++ b/internal/pkg/fxapp/application_builder.go @@ -1,7 +1,7 @@ package fxapp import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" loggerConfig "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/config" @@ -17,11 +17,11 @@ type applicationBuilder struct { decorates []interface{} options []fx.Option logger logger.Logger - environment environemnt.Environment + environment environment.Environment } -func NewApplicationBuilder(environments ...environemnt.Environment) contracts.ApplicationBuilder { - env := environemnt.ConfigAppEnv(environments...) +func NewApplicationBuilder(environments ...environment.Environment) contracts.ApplicationBuilder { + env := environment.ConfigAppEnv(environments...) var logger logger.Logger logoption, err := loggerConfig.ProvideLogConfig(env) @@ -70,6 +70,6 @@ func (a *applicationBuilder) Logger() logger.Logger { return a.logger } -func (a *applicationBuilder) Environment() environemnt.Environment { +func (a *applicationBuilder) Environment() environment.Environment { return a.environment } diff --git a/internal/pkg/fxapp/contracts/application.go b/internal/pkg/fxapp/contracts/application.go index e4036b6f..06ffd61a 100644 --- a/internal/pkg/fxapp/contracts/application.go +++ b/internal/pkg/fxapp/contracts/application.go @@ -3,7 +3,7 @@ package contracts import ( "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "go.uber.org/fx" @@ -17,5 +17,5 @@ type Application interface { Stop(ctx context.Context) error Wait() <-chan fx.ShutdownSignal Logger() logger.Logger - Environment() environemnt.Environment + Environment() environment.Environment } diff --git a/internal/pkg/fxapp/contracts/application_builder.go b/internal/pkg/fxapp/contracts/application_builder.go index c138a8a2..279d2458 100644 --- a/internal/pkg/fxapp/contracts/application_builder.go +++ b/internal/pkg/fxapp/contracts/application_builder.go @@ -1,7 +1,7 @@ package contracts import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "go.uber.org/fx" @@ -19,5 +19,5 @@ type ApplicationBuilder interface { GetDecorates() []interface{} Options() []fx.Option Logger() logger.Logger - Environment() environemnt.Environment + Environment() environment.Environment } diff --git a/internal/pkg/fxapp/test/test_app_fx.go b/internal/pkg/fxapp/test/test_app_fx.go index 74b61770..02ec7313 100644 --- a/internal/pkg/fxapp/test/test_app_fx.go +++ b/internal/pkg/fxapp/test/test_app_fx.go @@ -4,7 +4,7 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" @@ -19,7 +19,7 @@ func CreateFxTestApp( invokes []interface{}, options []fx.Option, logger logger.Logger, - environment environemnt.Environment, + environment environment.Environment, ) *fxtest.App { var opts []fx.Option diff --git a/internal/pkg/fxapp/test/test_application.go b/internal/pkg/fxapp/test/test_application.go index 706de421..b750b871 100644 --- a/internal/pkg/fxapp/test/test_application.go +++ b/internal/pkg/fxapp/test/test_application.go @@ -4,7 +4,7 @@ import ( "context" "os" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/constants" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" @@ -20,7 +20,7 @@ type testApplication struct { options []fx.Option invokes []interface{} logger logger.Logger - env environemnt.Environment + env environment.Environment tb fxtest.TB fxtestApp *fxtest.App } @@ -29,7 +29,7 @@ func (a *testApplication) Logger() logger.Logger { return a.logger } -func (a *testApplication) Environment() environemnt.Environment { +func (a *testApplication) Environment() environment.Environment { return a.env } @@ -39,7 +39,7 @@ func NewTestApplication( decorates []interface{}, options []fx.Option, logger logger.Logger, - env environemnt.Environment, + env environment.Environment, ) contracts.Application { return &testApplication{ tb: tb, diff --git a/internal/pkg/fxapp/test/test_application_builder.go b/internal/pkg/fxapp/test/test_application_builder.go index 5213caa2..05327e3d 100644 --- a/internal/pkg/fxapp/test/test_application_builder.go +++ b/internal/pkg/fxapp/test/test_application_builder.go @@ -1,7 +1,7 @@ package test import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" @@ -16,7 +16,7 @@ type TestApplicationBuilder struct { func NewTestApplicationBuilder(tb fxtest.TB) *TestApplicationBuilder { return &TestApplicationBuilder{ TB: tb, - ApplicationBuilder: fxapp.NewApplicationBuilder(environemnt.Test), + ApplicationBuilder: fxapp.NewApplicationBuilder(environment.Test), } } @@ -27,7 +27,7 @@ func (a *TestApplicationBuilder) Build() contracts.Application { a.GetDecorates(), a.Options(), a.Logger(), - environemnt.Test, + environment.Test, ) return app diff --git a/internal/pkg/go.mod b/internal/pkg/go.mod index 7e74380c..88d4b62d 100644 --- a/internal/pkg/go.mod +++ b/internal/pkg/go.mod @@ -33,7 +33,7 @@ require ( github.com/labstack/echo/v4 v4.11.1 github.com/lib/pq v1.10.9 github.com/mcuadros/go-defaults v1.2.0 - github.com/mehdihadeli/go-mediatr v1.2.0 + github.com/mehdihadeli/go-mediatr v1.3.0 github.com/michaelklishin/rabbit-hole v1.5.0 github.com/mitchellh/mapstructure v1.5.0 github.com/nolleh/caption_json_formatter v0.2.2 diff --git a/internal/pkg/go.sum b/internal/pkg/go.sum index b86ed166..cc48b9f9 100644 --- a/internal/pkg/go.sum +++ b/internal/pkg/go.sum @@ -466,6 +466,8 @@ github.com/mcuadros/go-defaults v1.2.0 h1:FODb8WSf0uGaY8elWJAkoLL0Ri6AlZ1bFlenk5 github.com/mcuadros/go-defaults v1.2.0/go.mod h1:WEZtHEVIGYVDqkKSWBdWKUVdRyKlMfulPaGDWIVeCWY= github.com/mehdihadeli/go-mediatr v1.2.0 h1:XkzYF/uGfW4pwPWYAxKyY+mO6l989PbmCQWSYHuCZtU= github.com/mehdihadeli/go-mediatr v1.2.0/go.mod h1:I9LuExxAKz6cTDJyP/SSDSmkHaPHK1/usnvEXjUY47k= +github.com/mehdihadeli/go-mediatr v1.3.0 h1:hrb5Scp/nsiR3Y62mjZ0Tc5UX/dRJl4nDFkINBEIESA= +github.com/mehdihadeli/go-mediatr v1.3.0/go.mod h1:lsG+hyH+pEOhmZiZl0KPO72BcZiEReF03CBk4GVJB0k= github.com/michaelklishin/rabbit-hole v1.5.0 h1:Bex27BiFDsijCM9D0ezSHqyy0kehpYHuNKaPqq/a4RM= github.com/michaelklishin/rabbit-hole v1.5.0/go.mod h1:vvI1uOitYZi0O5HEGXhaWC1XT80Gy+HvFheJ+5Krlhk= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= diff --git a/internal/pkg/gorm_postgres/gorm_options.go b/internal/pkg/gorm_postgres/gorm_options.go index 593d677e..eb414c63 100644 --- a/internal/pkg/gorm_postgres/gorm_options.go +++ b/internal/pkg/gorm_postgres/gorm_options.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" "github.com/iancoleman/strcase" @@ -34,6 +34,6 @@ func (h *GormOptions) Dns() string { return datasource } -func provideConfig(environment environemnt.Environment) (*GormOptions, error) { +func provideConfig(environment environment.Environment) (*GormOptions, error) { return config.BindConfigKey[*GormOptions](optionName, environment) } diff --git a/internal/pkg/grpc/config/grpc_options.go b/internal/pkg/grpc/config/grpc_options.go index 649ebed0..773b32c7 100644 --- a/internal/pkg/grpc/config/grpc_options.go +++ b/internal/pkg/grpc/config/grpc_options.go @@ -2,7 +2,7 @@ package config import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" "github.com/iancoleman/strcase" @@ -17,6 +17,6 @@ type GrpcOptions struct { Name string `mapstructure:"name" env:"Name"` } -func ProvideConfig(environment environemnt.Environment) (*GrpcOptions, error) { +func ProvideConfig(environment environment.Environment) (*GrpcOptions, error) { return config.BindConfigKey[*GrpcOptions](optionName, environment) } diff --git a/internal/pkg/http/custom_echo/config/echo_http_options.go b/internal/pkg/http/custom_echo/config/echo_http_options.go index fbce4deb..290de0ea 100644 --- a/internal/pkg/http/custom_echo/config/echo_http_options.go +++ b/internal/pkg/http/custom_echo/config/echo_http_options.go @@ -5,7 +5,7 @@ import ( "net/url" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" "github.com/iancoleman/strcase" @@ -36,6 +36,6 @@ func (c *EchoHttpOptions) BasePathAddress() string { return path } -func ProvideConfig(environment environemnt.Environment) (*EchoHttpOptions, error) { +func ProvideConfig(environment environment.Environment) (*EchoHttpOptions, error) { return config.BindConfigKey[*EchoHttpOptions](optionName, environment) } diff --git a/internal/pkg/http/custom_echo/middlewares/ip_ratelimit/ip_ratelimit.go b/internal/pkg/http/custom_echo/middlewares/ip_ratelimit/ip_ratelimit.go index 4d069f60..df833a22 100644 --- a/internal/pkg/http/custom_echo/middlewares/ip_ratelimit/ip_ratelimit.go +++ b/internal/pkg/http/custom_echo/middlewares/ip_ratelimit/ip_ratelimit.go @@ -44,6 +44,7 @@ func IPRateLimit(opts ...Option) echo.MiddlewareFunc { ip, c.Request().URL, ) + return c.JSON(http.StatusInternalServerError, echo.Map{ "success": false, "message": err, @@ -64,6 +65,7 @@ func IPRateLimit(opts ...Option) echo.MiddlewareFunc { ip, c.Request().URL, ) + return c.JSON(http.StatusTooManyRequests, echo.Map{ "success": false, "message": "Too Many Requests on " + c.Request().URL.String(), diff --git a/internal/pkg/logger/config/log_options.go b/internal/pkg/logger/config/log_options.go index 6af62b1d..a297d1e1 100644 --- a/internal/pkg/logger/config/log_options.go +++ b/internal/pkg/logger/config/log_options.go @@ -2,7 +2,7 @@ package config import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/models" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" @@ -18,6 +18,6 @@ type LogOptions struct { EnableTracing bool `mapstructure:"enableTracing" default:"true"` } -func ProvideLogConfig(env environemnt.Environment) (*LogOptions, error) { +func ProvideLogConfig(env environment.Environment) (*LogOptions, error) { return config.BindConfigKey[*LogOptions](optionName, env) } diff --git a/internal/pkg/logger/logrous/logrous_logger.go b/internal/pkg/logger/logrous/logrous_logger.go index efa57373..c3539de4 100644 --- a/internal/pkg/logger/logrous/logrous_logger.go +++ b/internal/pkg/logger/logrous/logrous_logger.go @@ -4,7 +4,7 @@ import ( "os" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/constants" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" config2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/config" @@ -35,7 +35,7 @@ var loggerLevelMap = map[string]logrus.Level{ // NewLogrusLogger creates a new logrus logger func NewLogrusLogger( cfg *config2.LogOptions, - env environemnt.Environment, + env environment.Environment, ) logger.Logger { logrusLogger := &logrusLogger{level: cfg.LogLevel, logOptions: cfg} logrusLogger.initLogger(env) @@ -44,7 +44,7 @@ func NewLogrusLogger( } // InitLogger Init logger -func (l *logrusLogger) initLogger(env environemnt.Environment) { +func (l *logrusLogger) initLogger(env environment.Environment) { logLevel := l.GetLoggerLevel() // Create a new instance of the logger. You can have any number of instances. diff --git a/internal/pkg/logger/zap/zap_logger.go b/internal/pkg/logger/zap/zap_logger.go index 6407c960..7f73402e 100644 --- a/internal/pkg/logger/zap/zap_logger.go +++ b/internal/pkg/logger/zap/zap_logger.go @@ -4,7 +4,7 @@ import ( "os" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/constants" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" config2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/config" @@ -43,7 +43,7 @@ var loggerLevelMap = map[string]zapcore.Level{ // NewZapLogger create new zap logger func NewZapLogger( cfg *config2.LogOptions, - env environemnt.Environment, + env environment.Environment, ) ZapLogger { zapLogger := &zapLogger{level: cfg.LogLevel, logOptions: cfg} zapLogger.initLogger(env) @@ -65,7 +65,7 @@ func (l *zapLogger) getLoggerLevel() zapcore.Level { } // InitLogger Init logger -func (l *zapLogger) initLogger(env environemnt.Environment) { +func (l *zapLogger) initLogger(env environment.Environment) { logLevel := l.getLoggerLevel() logWriter := zapcore.AddSync(os.Stdout) diff --git a/internal/pkg/messaging/pipeline/consumer_pipeline.go b/internal/pkg/messaging/pipeline/consumer_pipeline.go index 05c2165b..4aff0d9c 100644 --- a/internal/pkg/messaging/pipeline/consumer_pipeline.go +++ b/internal/pkg/messaging/pipeline/consumer_pipeline.go @@ -7,7 +7,7 @@ import ( ) // ConsumerHandlerFunc is a continuation for the next task to execute in the pipeline -type ConsumerHandlerFunc func() error +type ConsumerHandlerFunc func(ctx context.Context) error // ConsumerPipeline is a Pipeline for wrapping the inner consumer handler. type ConsumerPipeline interface { diff --git a/internal/pkg/migration/migration_options.go b/internal/pkg/migration/migration_options.go index 99997a0e..15d65ccb 100644 --- a/internal/pkg/migration/migration_options.go +++ b/internal/pkg/migration/migration_options.go @@ -2,7 +2,7 @@ package migration import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" "github.com/iancoleman/strcase" @@ -27,7 +27,7 @@ type MigrationOptions struct { SkipMigration bool `mapstructure:"skipMigration"` } -func ProvideConfig(environment environemnt.Environment) (*MigrationOptions, error) { +func ProvideConfig(environment environment.Environment) (*MigrationOptions, error) { optionName := strcase.ToLowerCamel(typeMapper.GetTypeNameByT[MigrationOptions]()) return config.BindConfigKey[*MigrationOptions](optionName, environment) diff --git a/internal/pkg/mongodb/mongo_options.go b/internal/pkg/mongodb/mongo_options.go index a7c912de..4ff3a0f8 100644 --- a/internal/pkg/mongodb/mongo_options.go +++ b/internal/pkg/mongodb/mongo_options.go @@ -2,7 +2,7 @@ package mongodb import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" "github.com/iancoleman/strcase" @@ -19,7 +19,7 @@ type MongoDbOptions struct { } func provideConfig( - environment environemnt.Environment, + environment environment.Environment, ) (*MongoDbOptions, error) { optionName := strcase.ToLowerCamel( typeMapper.GetTypeNameByT[MongoDbOptions](), diff --git a/internal/pkg/otel/metrics/pipelines/config.go b/internal/pkg/otel/metrics/mediatr/pipelines/config.go similarity index 100% rename from internal/pkg/otel/metrics/pipelines/config.go rename to internal/pkg/otel/metrics/mediatr/pipelines/config.go diff --git a/internal/pkg/otel/metrics/pipelines/metrics_pipeline.go b/internal/pkg/otel/metrics/mediatr/pipelines/mediator_metrics_pipeline.go similarity index 88% rename from internal/pkg/otel/metrics/pipelines/metrics_pipeline.go rename to internal/pkg/otel/metrics/mediatr/pipelines/mediator_metrics_pipeline.go index 60c0e19d..4e83b4ab 100644 --- a/internal/pkg/otel/metrics/pipelines/metrics_pipeline.go +++ b/internal/pkg/otel/metrics/mediatr/pipelines/mediator_metrics_pipeline.go @@ -16,12 +16,12 @@ import ( "go.opentelemetry.io/otel/metric" ) -type metricsPipeline struct { +type mediatorMetricsPipeline struct { config *config meter metrics.AppMetrics } -func NewMetricsPipeline( +func NewMediatorMetricsPipeline( appMetrics metrics.AppMetrics, opts ...Option, ) mediatr.PipelineBehavior { @@ -30,13 +30,13 @@ func NewMetricsPipeline( opt.apply(cfg) } - return &metricsPipeline{ + return &mediatorMetricsPipeline{ config: cfg, meter: appMetrics, } } -func (r *metricsPipeline) Handle( +func (r *mediatorMetricsPipeline) Handle( ctx context.Context, request interface{}, next mediatr.RequestHandlerFunc, @@ -70,7 +70,6 @@ func (r *metricsPipeline) Handle( requestType = "event" } - // Create instruments for success requests, failed requests, and duration successRequestsCounter, err := r.meter.Int64Counter( fmt.Sprintf("%s.success_total", requestName), metric.WithUnit("count"), @@ -101,6 +100,21 @@ func (r *metricsPipeline) Handle( return nil, err } + totalRequestsCounter, err := r.meter.Int64Counter( + fmt.Sprintf("%s.total", requestName), + metric.WithUnit("count"), + metric.WithDescription( + fmt.Sprintf( + "Measures the total number of '%s' %s", + requestName, + requestType, + ), + ), + ) + if err != nil { + return nil, err + } + durationValueRecorder, err := r.meter.Int64Histogram( fmt.Sprintf("%s.duration", requestName), metric.WithUnit("ms"), @@ -133,6 +147,8 @@ func (r *metricsPipeline) Handle( ) // Record metrics + totalRequestsCounter.Add(ctx, 1, opt) + if err == nil { successRequestsCounter.Add(ctx, 1, opt) } else { diff --git a/internal/pkg/otel/tracing/pipelines/config.go b/internal/pkg/otel/metrics/messaging/pipeline/config.go similarity index 100% rename from internal/pkg/otel/tracing/pipelines/config.go rename to internal/pkg/otel/metrics/messaging/pipeline/config.go diff --git a/internal/pkg/otel/metrics/messaging/pipeline/messaging_metrics_pipeline.go b/internal/pkg/otel/metrics/messaging/pipeline/messaging_metrics_pipeline.go new file mode 100644 index 00000000..049122f8 --- /dev/null +++ b/internal/pkg/otel/metrics/messaging/pipeline/messaging_metrics_pipeline.go @@ -0,0 +1,258 @@ +package pipelines + +import ( + "context" + "fmt" + "time" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/pipeline" + types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" + attribute2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" +) + +type messagingMetricsPipeline struct { + config *config + meter metrics.AppMetrics +} + +func NewMessagingMetricsPipeline( + appMetrics metrics.AppMetrics, + opts ...Option, +) pipeline.ConsumerPipeline { + cfg := defaultConfig + for _, opt := range opts { + opt.apply(cfg) + } + + return &messagingMetricsPipeline{ + config: cfg, + meter: appMetrics, + } +} + +func (m *messagingMetricsPipeline) Handle( + ctx context.Context, + consumerContext types2.MessageConsumeContext, + next pipeline.ConsumerHandlerFunc, +) error { + message := consumerContext.Message() + + successRequestsCounter, err := m.meter.Int64Counter( + fmt.Sprintf("%s.success_total", requestName), + metric.WithUnit("count"), + metric.WithDescription( + fmt.Sprintf( + "Measures the number of success '%s' %s", + requestName, + requestType, + ), + ), + ) + if err != nil { + return err + } + + failedRequestsCounter, err := r.meter.Int64Counter( + fmt.Sprintf("%s.failed_total", requestName), + metric.WithUnit("count"), + metric.WithDescription( + fmt.Sprintf( + "Measures the number of failed '%s' %s", + requestName, + requestType, + ), + ), + ) + if err != nil { + return err + } + + totalRequestsCounter, err := r.meter.Int64Counter( + fmt.Sprintf("%s.total", requestName), + metric.WithUnit("count"), + metric.WithDescription( + fmt.Sprintf( + "Measures the total number of '%s' %s", + requestName, + requestType, + ), + ), + ) + if err != nil { + return err + } + + durationValueRecorder, err := r.meter.Int64Histogram( + fmt.Sprintf("%s.duration", requestName), + metric.WithUnit("ms"), + metric.WithDescription( + fmt.Sprintf( + "Measures the duration of '%s' %s", + requestName, + requestType, + ), + ), + ) + if err != nil { + return err + } + + // Start recording the duration + startTime := time.Now() + + response, err := next(ctx) + + // Calculate the duration + duration := time.Since(startTime).Milliseconds() + + responseName := typeMapper.GetSnakeTypeName(response) + opt := metric.WithAttributes( + attribute.String(requestNameAttribute, requestName), + attribute2.Object(requestAttribute, request), + attribute.String(requestResultName, responseName), + attribute2.Object(requestResult, response), + ) + + // Record metrics + totalRequestsCounter.Add(ctx, 1, opt) + + if err == nil { + successRequestsCounter.Add(ctx, 1, opt) + } else { + failedRequestsCounter.Add(ctx, 1, opt) + } + + durationValueRecorder.Record(ctx, duration, opt) + + return nil +} + +// +//func (r *messagingMetricsPipeline) Handle( +// ctx context.Context, +// request interface{}, +// next mediatr.RequestHandlerFunc, +//) (interface{}, error) { +// requestName := typeMapper.GetSnakeTypeName(request) +// +// requestNameAttribute := app.RequestName +// requestAttribute := app.Request +// requestResultName := app.RequestResultName +// requestResult := app.RequestResult +// requestType := "request" +// +// switch { +// case strings.Contains(typeMapper.GetPackageName(request), "command") || strings.Contains(typeMapper.GetPackageName(request), "commands"): +// requestNameAttribute = app.CommandName +// requestAttribute = app.Command +// requestResultName = app.CommandResultName +// requestResult = app.CommandResult +// requestType = "command" +// case strings.Contains(typeMapper.GetPackageName(request), "query") || strings.Contains(typeMapper.GetPackageName(request), "queries"): +// requestNameAttribute = app.QueryName +// requestAttribute = app.Query +// requestResultName = app.QueryResultName +// requestResult = app.QueryResult +// requestType = "query" +// case strings.Contains(typeMapper.GetPackageName(request), "event") || strings.Contains(typeMapper.GetPackageName(request), "events"): +// requestNameAttribute = app.EventName +// requestAttribute = app.Event +// requestResultName = app.EventResultName +// requestResult = app.EventResult +// requestType = "event" +// } +// +// successRequestsCounter, err := r.meter.Int64Counter( +// fmt.Sprintf("%s.success_total", requestName), +// metric.WithUnit("count"), +// metric.WithDescription( +// fmt.Sprintf( +// "Measures the number of success '%s' %s", +// requestName, +// requestType, +// ), +// ), +// ) +// if err != nil { +// return nil, err +// } +// +// failedRequestsCounter, err := r.meter.Int64Counter( +// fmt.Sprintf("%s.failed_total", requestName), +// metric.WithUnit("count"), +// metric.WithDescription( +// fmt.Sprintf( +// "Measures the number of failed '%s' %s", +// requestName, +// requestType, +// ), +// ), +// ) +// if err != nil { +// return nil, err +// } +// +// totalRequestsCounter, err := r.meter.Int64Counter( +// fmt.Sprintf("%s.total", requestName), +// metric.WithUnit("count"), +// metric.WithDescription( +// fmt.Sprintf( +// "Measures the total number of '%s' %s", +// requestName, +// requestType, +// ), +// ), +// ) +// if err != nil { +// return nil, err +// } +// +// durationValueRecorder, err := r.meter.Int64Histogram( +// fmt.Sprintf("%s.duration", requestName), +// metric.WithUnit("ms"), +// metric.WithDescription( +// fmt.Sprintf( +// "Measures the duration of '%s' %s", +// requestName, +// requestType, +// ), +// ), +// ) +// if err != nil { +// return nil, err +// } +// +// // Start recording the duration +// startTime := time.Now() +// +// response, err := next(ctx) +// +// // Calculate the duration +// duration := time.Since(startTime).Milliseconds() +// +// responseName := typeMapper.GetSnakeTypeName(response) +// opt := metric.WithAttributes( +// attribute.String(requestNameAttribute, requestName), +// attribute2.Object(requestAttribute, request), +// attribute.String(requestResultName, responseName), +// attribute2.Object(requestResult, response), +// ) +// +// // Record metrics +// totalRequestsCounter.Add(ctx, 1, opt) +// +// if err == nil { +// successRequestsCounter.Add(ctx, 1, opt) +// } else { +// failedRequestsCounter.Add(ctx, 1, opt) +// } +// +// durationValueRecorder.Record(ctx, duration, opt) +// +// return response, err +//} diff --git a/internal/pkg/otel/metrics/metrics.go b/internal/pkg/otel/metrics/metrics.go index 1f42595d..a2344bb4 100644 --- a/internal/pkg/otel/metrics/metrics.go +++ b/internal/pkg/otel/metrics/metrics.go @@ -8,7 +8,7 @@ import ( "context" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" @@ -30,7 +30,7 @@ type OtelMetrics struct { config *MetricsOptions logger logger.Logger appMetrics AppMetrics - environment environemnt.Environment + environment environment.Environment provider *metric.MeterProvider } @@ -38,7 +38,7 @@ type OtelMetrics struct { func NewOtelMetrics( config *MetricsOptions, logger logger.Logger, - environment environemnt.Environment, + environment environment.Environment, ) (*OtelMetrics, error) { if config == nil { return nil, errors.New("metrics config can't be nil") diff --git a/internal/pkg/otel/metrics/metrics_options.go b/internal/pkg/otel/metrics/metrics_options.go index a0536676..07ca912e 100644 --- a/internal/pkg/otel/metrics/metrics_options.go +++ b/internal/pkg/otel/metrics/metrics_options.go @@ -2,7 +2,7 @@ package metrics import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" "github.com/iancoleman/strcase" @@ -32,7 +32,7 @@ type MetricsOptions struct { } func ProvideMetricsConfig( - environment environemnt.Environment, + environment environment.Environment, ) (*MetricsOptions, error) { optionName := strcase.ToLowerCamel( typeMapper.GetTypeNameByT[MetricsOptions](), diff --git a/internal/pkg/otel/tracing/mediatr/pipelines/config.go b/internal/pkg/otel/tracing/mediatr/pipelines/config.go new file mode 100644 index 00000000..e344c53d --- /dev/null +++ b/internal/pkg/otel/tracing/mediatr/pipelines/config.go @@ -0,0 +1,43 @@ +package pipelines + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" +) + +type config struct { + logger logger.Logger + serviceName string +} + +var defaultConfig = &config{ + serviceName: "app", + logger: defaultLogger.GetLogger(), +} + +// Option specifies instrumentation configuration options. +type Option interface { + apply(*config) +} + +type optionFunc func(*config) + +func (o optionFunc) apply(c *config) { + o(c) +} + +func WithServiceName(v string) Option { + return optionFunc(func(cfg *config) { + if cfg.serviceName != "" { + cfg.serviceName = v + } + }) +} + +func WithLogger(l logger.Logger) Option { + return optionFunc(func(cfg *config) { + if cfg.logger != nil { + cfg.logger = l + } + }) +} diff --git a/internal/pkg/otel/tracing/pipelines/tracing_pipeline.go b/internal/pkg/otel/tracing/mediatr/pipelines/mediator_tracing_pipeline.go similarity index 95% rename from internal/pkg/otel/tracing/pipelines/tracing_pipeline.go rename to internal/pkg/otel/tracing/mediatr/pipelines/mediator_tracing_pipeline.go index 9b6851e2..5691cb89 100644 --- a/internal/pkg/otel/tracing/pipelines/tracing_pipeline.go +++ b/internal/pkg/otel/tracing/mediatr/pipelines/mediator_tracing_pipeline.go @@ -17,12 +17,12 @@ import ( "go.opentelemetry.io/otel/attribute" ) -type tracingPipeline struct { +type mediatorTracingPipeline struct { config *config tracer tracing.AppTracer } -func NewTracingPipeline( +func NewMediatorTracingPipeline( appTracer tracing.AppTracer, opts ...Option, ) mediatr.PipelineBehavior { @@ -31,13 +31,13 @@ func NewTracingPipeline( opt.apply(cfg) } - return &tracingPipeline{ + return &mediatorTracingPipeline{ config: cfg, tracer: appTracer, } } -func (r *tracingPipeline) Handle( +func (r *mediatorTracingPipeline) Handle( ctx context.Context, request interface{}, next mediatr.RequestHandlerFunc, diff --git a/internal/pkg/otel/tracing/tracing.go b/internal/pkg/otel/tracing/tracing.go index fa013169..d93521e3 100644 --- a/internal/pkg/otel/tracing/tracing.go +++ b/internal/pkg/otel/tracing/tracing.go @@ -16,7 +16,7 @@ import ( "os" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "emperror.dev/errors" "github.com/samber/lo" @@ -34,7 +34,7 @@ import ( type TracingOpenTelemetry struct { config *TracingOptions - environment environemnt.Environment + environment environment.Environment appTracer AppTracer provider *tracesdk.TracerProvider } @@ -44,7 +44,7 @@ type TracingOpenTelemetry struct { func NewOtelTracing( config *TracingOptions, - environment environemnt.Environment, + environment environment.Environment, ) (*TracingOpenTelemetry, error) { otelTracing := &TracingOpenTelemetry{ config: config, diff --git a/internal/pkg/otel/tracing/tracing_options.go b/internal/pkg/otel/tracing/tracing_options.go index fbebbf3a..276e0e06 100644 --- a/internal/pkg/otel/tracing/tracing_options.go +++ b/internal/pkg/otel/tracing/tracing_options.go @@ -2,7 +2,7 @@ package tracing import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" "github.com/iancoleman/strcase" @@ -38,7 +38,7 @@ type ZipkinExporterOptions struct { } func ProvideTracingConfig( - environment environemnt.Environment, + environment environment.Environment, ) (*TracingOptions, error) { optionName := strcase.ToLowerCamel( typeMapper.GetTypeNameByT[TracingOptions](), diff --git a/internal/pkg/postgres_pgx/postgres_pgx_options.go b/internal/pkg/postgres_pgx/postgres_pgx_options.go index 936e50dd..4fa2f0e1 100644 --- a/internal/pkg/postgres_pgx/postgres_pgx_options.go +++ b/internal/pkg/postgres_pgx/postgres_pgx_options.go @@ -2,7 +2,7 @@ package postgres import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" "github.com/iancoleman/strcase" @@ -20,6 +20,6 @@ type PostgresPgxOptions struct { LogLevel int `mapstructure:"logLevel"` } -func provideConfig(environment environemnt.Environment) (*PostgresPgxOptions, error) { +func provideConfig(environment environment.Environment) (*PostgresPgxOptions, error) { return config.BindConfigKey[*PostgresPgxOptions](optionName, environment) } diff --git a/internal/pkg/postgres_sqlx/postgres_sqlx_options.go b/internal/pkg/postgres_sqlx/postgres_sqlx_options.go index 79519c97..2f81d406 100644 --- a/internal/pkg/postgres_sqlx/postgres_sqlx_options.go +++ b/internal/pkg/postgres_sqlx/postgres_sqlx_options.go @@ -2,7 +2,7 @@ package postgressqlx import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" "github.com/iancoleman/strcase" @@ -19,6 +19,6 @@ type PostgresSqlxOptions struct { Password string `mapstructure:"password"` } -func provideConfig(environment environemnt.Environment) (*PostgresSqlxOptions, error) { +func provideConfig(environment environment.Environment) (*PostgresSqlxOptions, error) { return config.BindConfigKey[*PostgresSqlxOptions](optionName, environment) } diff --git a/internal/pkg/rabbitmq/bus/rabbitmq-bus.go b/internal/pkg/rabbitmq/bus/rabbitmq-bus.go index 42dec919..95f7355f 100644 --- a/internal/pkg/rabbitmq/bus/rabbitmq-bus.go +++ b/internal/pkg/rabbitmq/bus/rabbitmq-bus.go @@ -7,21 +7,18 @@ import ( "sync" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/bus" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/utils" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" - consumer2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer" consumerConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" - producer2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/consumercontracts" producerConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/configurations" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/producercontracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/rabbitmqErrors" - types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" "emperror.dev/errors" @@ -37,20 +34,18 @@ type rabbitmqBus struct { messageTypeConsumers map[reflect.Type][]consumer.Consumer producer producer.Producer rabbitmqConfiguration *configurations.RabbitMQConfiguration - rabbitmqConfig *config.RabbitmqOptions rabbitmqConfigBuilder configurations.RabbitMQConfigurationBuilder logger logger.Logger - serializer serializer.EventSerializer - rabbitmqConnection types2.IConnection + consumerFactory consumercontracts.ConsumerFactory + producerFactory producercontracts.ProducerFactory isConsumedNotifications []func(message types.IMessage) isProducedNotifications []func(message types.IMessage) } func NewRabbitmqBus( - cfg *config.RabbitmqOptions, - serializer serializer.EventSerializer, logger logger.Logger, - connection types2.IConnection, + consumerFactory consumercontracts.ConsumerFactory, + producerFactory producercontracts.ProducerFactory, rabbitmqBuilderFunc configurations.RabbitMQConfigurationBuilderFuc, ) (RabbitmqBus, error) { builder := configurations.NewRabbitMQConfigurationBuilder() @@ -61,15 +56,16 @@ func NewRabbitmqBus( rabbitmqConfiguration := builder.Build() rabbitBus := &rabbitmqBus{ logger: logger, - serializer: serializer, rabbitmqConfiguration: rabbitmqConfiguration, - rabbitmqConfig: cfg, + consumerFactory: consumerFactory, + producerFactory: producerFactory, rabbitmqConfigBuilder: builder, messageTypeConsumers: map[reflect.Type][]consumer.Consumer{}, - rabbitmqConnection: connection, } - producersConfigurationMap := make(map[string]*producerConfigurations.RabbitMQProducerConfiguration) + producersConfigurationMap := make( + map[string]*producerConfigurations.RabbitMQProducerConfiguration, + ) lo.ForEach( rabbitBus.rabbitmqConfiguration.ProducersConfigurations, func(config *producerConfigurations.RabbitMQProducerConfiguration, index int) { @@ -78,7 +74,9 @@ func NewRabbitmqBus( }, ) - consumersConfigurationMap := make(map[string]*consumerConfigurations.RabbitMQConsumerConfiguration) + consumersConfigurationMap := make( + map[string]*consumerConfigurations.RabbitMQConsumerConfiguration, + ) lo.ForEach( rabbitBus.rabbitmqConfiguration.ConsumersConfigurations, func(config *consumerConfigurations.RabbitMQConsumerConfiguration, index int) { @@ -88,11 +86,8 @@ func NewRabbitmqBus( ) for _, consumerConfiguration := range consumersConfigurationMap { - mqConsumer, err := consumer2.NewRabbitMQConsumer( - rabbitBus.rabbitmqConnection, + mqConsumer, err := consumerFactory.CreateConsumer( consumerConfiguration, - rabbitBus.serializer, - rabbitBus.logger, // IsConsumed Notification func(message types.IMessage) { if rabbitBus.isConsumedNotifications != nil { @@ -111,11 +106,8 @@ func NewRabbitmqBus( ) } - mqProducer, err := producer2.NewRabbitMQProducer( - rabbitBus.rabbitmqConnection, + mqProducer, err := producerFactory.CreateProducer( producersConfigurationMap, - rabbitBus.logger, - rabbitBus.serializer, // IsProduced Notification func(message types.IMessage) { if rabbitBus.isProducedNotifications != nil { @@ -148,7 +140,10 @@ func (r *rabbitmqBus) ConnectConsumer( ) error { typeName := utils.GetMessageBaseReflectType(messageType) - r.messageTypeConsumers[typeName] = append(r.messageTypeConsumers[typeName], consumer) + r.messageTypeConsumers[typeName] = append( + r.messageTypeConsumers[typeName], + consumer, + ) return nil } @@ -160,16 +155,15 @@ func (r *rabbitmqBus) ConnectRabbitMQConsumer( ) error { typeName := utils.GetMessageBaseReflectType(messageType) - builder := consumerConfigurations.NewRabbitMQConsumerConfigurationBuilder(messageType) + builder := consumerConfigurations.NewRabbitMQConsumerConfigurationBuilder( + messageType, + ) if consumerBuilderFunc != nil { consumerBuilderFunc(builder) } consumerConfig := builder.Build() - mqConsumer, err := consumer2.NewRabbitMQConsumer( - r.rabbitmqConnection, + mqConsumer, err := r.consumerFactory.CreateConsumer( consumerConfig, - r.serializer, - r.logger, // IsConsumed Notification func(message types.IMessage) { if len(r.isConsumedNotifications) > 0 { @@ -185,7 +179,10 @@ func (r *rabbitmqBus) ConnectRabbitMQConsumer( return err } - r.messageTypeConsumers[typeName] = append(r.messageTypeConsumers[typeName], mqConsumer) + r.messageTypeConsumers[typeName] = append( + r.messageTypeConsumers[typeName], + mqConsumer, + ) return nil } @@ -210,11 +207,8 @@ func (r *rabbitmqBus) ConnectConsumerHandler( builder.AddHandler(consumerHandler) }) consumerConfig := consumerBuilder.Build() - mqConsumer, err := consumer2.NewRabbitMQConsumer( - r.rabbitmqConnection, + mqConsumer, err := r.consumerFactory.CreateConsumer( consumerConfig, - r.serializer, - r.logger, // IsConsumed Notification func(message types.IMessage) { if len(r.isConsumedNotifications) > 0 { @@ -238,7 +232,7 @@ func (r *rabbitmqBus) ConnectConsumerHandler( func (r *rabbitmqBus) Start(ctx context.Context) error { r.logger.Infof( "rabbitmq is running on host: %s", - r.rabbitmqConnection.Raw().LocalAddr().String(), + r.consumerFactory.Connection().Raw().LocalAddr().String(), ) for messageType, consumers := range r.messageTypeConsumers { @@ -323,5 +317,10 @@ func (r *rabbitmqBus) PublishMessageWithTopicName( meta metadata.Metadata, topicOrExchangeName string, ) error { - return r.producer.PublishMessageWithTopicName(ctx, message, meta, topicOrExchangeName) + return r.producer.PublishMessageWithTopicName( + ctx, + message, + meta, + topicOrExchangeName, + ) } diff --git a/internal/pkg/rabbitmq/bus/rabbitmq_bus_test.go b/internal/pkg/rabbitmq/bus/rabbitmq_bus_test.go index 65831517..b65c5fa4 100644 --- a/internal/pkg/rabbitmq/bus/rabbitmq_bus_test.go +++ b/internal/pkg/rabbitmq/bus/rabbitmq_bus_test.go @@ -164,7 +164,7 @@ func NewPipeline1() pipeline.ConsumerPipeline { return &Pipeline1{} } -func (p Pipeline1) Handle( +func (p *Pipeline1) Handle( ctx context.Context, consumerContext types2.MessageConsumeContext, next pipeline.ConsumerHandlerFunc, diff --git a/internal/pkg/rabbitmq/config/rabbitmq_options.go b/internal/pkg/rabbitmq/config/rabbitmq_options.go index fa3bb8f7..15aa7d9d 100644 --- a/internal/pkg/rabbitmq/config/rabbitmq_options.go +++ b/internal/pkg/rabbitmq/config/rabbitmq_options.go @@ -5,7 +5,7 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" "github.com/iancoleman/strcase" @@ -38,7 +38,7 @@ func (h *RabbitmqHostOptions) HttpEndPoint() string { return fmt.Sprintf("http://%s:%d", h.HostName, h.HttpPort) } -func ProvideConfig(environment environemnt.Environment) (*RabbitmqOptions, error) { +func ProvideConfig(environment environment.Environment) (*RabbitmqOptions, error) { optionName := strcase.ToLowerCamel(typeMapper.GetTypeNameByT[RabbitmqOptions]()) cfg, err := config.BindConfigKey[*RabbitmqOptions](optionName, environment) diff --git a/internal/pkg/rabbitmq/consumer/consumercontracts/consumer_factory.go b/internal/pkg/rabbitmq/consumer/consumercontracts/consumer_factory.go new file mode 100644 index 00000000..c3cae785 --- /dev/null +++ b/internal/pkg/rabbitmq/consumer/consumercontracts/consumer_factory.go @@ -0,0 +1,17 @@ +package consumercontracts + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" + messagingTypes "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" +) + +type ConsumerFactory interface { + CreateConsumer( + consumerConfiguration *configurations.RabbitMQConsumerConfiguration, + isConsumedNotifications ...func(message messagingTypes.IMessage), + ) (consumer.Consumer, error) + + Connection() types.IConnection +} diff --git a/internal/pkg/rabbitmq/consumer/factory/consumer_factory.go b/internal/pkg/rabbitmq/consumer/factory/consumer_factory.go new file mode 100644 index 00000000..728876e1 --- /dev/null +++ b/internal/pkg/rabbitmq/consumer/factory/consumer_factory.go @@ -0,0 +1,51 @@ +package factory + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" + rabbitmqconsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer" + consumerConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/consumercontracts" + types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" +) + +type consumerFactory struct { + connection types2.IConnection + eventSerializer serializer.EventSerializer + logger logger.Logger + rabbitmqOptions *config.RabbitmqOptions +} + +func NewConsumerFactory( + rabbitmqOptions *config.RabbitmqOptions, + connection types2.IConnection, + eventSerializer serializer.EventSerializer, + l logger.Logger, +) consumercontracts.ConsumerFactory { + return &consumerFactory{ + rabbitmqOptions: rabbitmqOptions, + logger: l, + eventSerializer: eventSerializer, + connection: connection, + } +} + +func (c *consumerFactory) CreateConsumer( + consumerConfiguration *consumerConfigurations.RabbitMQConsumerConfiguration, + isConsumedNotifications ...func(message types.IMessage), +) (consumer.Consumer, error) { + return rabbitmqconsumer.NewRabbitMQConsumer( + c.rabbitmqOptions, + c.connection, + consumerConfiguration, + c.eventSerializer, + c.logger, + isConsumedNotifications...) +} + +func (c *consumerFactory) Connection() types2.IConnection { + return c.connection +} diff --git a/internal/pkg/rabbitmq/consumer/rabbitmq_consumer.go b/internal/pkg/rabbitmq/consumer/rabbitmq_consumer.go index b7e152fb..916df05b 100644 --- a/internal/pkg/rabbitmq/consumer/rabbitmq_consumer.go +++ b/internal/pkg/rabbitmq/consumer/rabbitmq_consumer.go @@ -14,6 +14,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/pipeline" messagingTypes "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/utils" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/rabbitmqErrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" @@ -46,6 +47,7 @@ type rabbitMQConsumer struct { deliveryRoutines chan struct{} // chan should init before using channel eventSerializer serializer.EventSerializer logger logger.Logger + rabbitmqOptions *config.RabbitmqOptions ErrChan chan error handlers []consumer.ConsumerHandler pipelines []pipeline.ConsumerPipeline @@ -54,6 +56,7 @@ type rabbitMQConsumer struct { // NewRabbitMQConsumer create a new generic RabbitMQ consumer func NewRabbitMQConsumer( + rabbitmqOptions *config.RabbitmqOptions, connection types.IConnection, consumerConfiguration *configurations.RabbitMQConsumerConfiguration, eventSerializer serializer.EventSerializer, @@ -65,12 +68,18 @@ func NewRabbitMQConsumer( } if consumerConfiguration.ConsumerMessageType == nil { - return nil, errors.New("consumer ConsumerMessageType property is required") + return nil, errors.New( + "consumer ConsumerMessageType property is required", + ) } - deliveryRoutines := make(chan struct{}, consumerConfiguration.ConcurrencyLimit) + deliveryRoutines := make( + chan struct{}, + consumerConfiguration.ConcurrencyLimit, + ) cons := &rabbitMQConsumer{ eventSerializer: eventSerializer, + rabbitmqOptions: rabbitmqOptions, logger: logger, rabbitmqConsumerOptions: consumerConfiguration, deliveryRoutines: deliveryRoutines, @@ -262,10 +271,15 @@ func (r *rabbitMQConsumer) reConsumeOnDropConnection(ctx context.Context) { r.logger.Info("reconsume_on_drop_connection started") err := r.Start(ctx) if err != nil { - r.logger.Error("reconsume_on_drop_connection finished with error: %v", err) + r.logger.Error( + "reconsume_on_drop_connection finished with error: %v", + err, + ) continue } - r.logger.Info("reconsume_on_drop_connection finished successfully") + r.logger.Info( + "reconsume_on_drop_connection finished successfully", + ) return } } @@ -273,7 +287,10 @@ func (r *rabbitMQConsumer) reConsumeOnDropConnection(ctx context.Context) { }() } -func (r *rabbitMQConsumer) handleReceived(ctx context.Context, delivery amqp091.Delivery) { +func (r *rabbitMQConsumer) handleReceived( + ctx context.Context, + delivery amqp091.Delivery, +) { // for ensuring our handlers execute completely after shutdown r.deliveryRoutines <- struct{}{} @@ -301,7 +318,9 @@ func (r *rabbitMQConsumer) handleReceived(ctx context.Context, delivery amqp091. consumeContext, err := r.createConsumeContext(delivery) if err != nil { - r.logger.Error(consumeTracing.FinishConsumerSpan(beforeConsumeSpan, err)) + r.logger.Error( + consumeTracing.FinishConsumerSpan(beforeConsumeSpan, err), + ) return } @@ -379,7 +398,7 @@ func (r *rabbitMQConsumer) runHandlersWithRetry( if r.pipelines != nil && len(r.pipelines) > 0 { reversPipes := r.reversOrder(r.pipelines) - lastHandler = func() error { + lastHandler = func(ctx context.Context) error { handler := handler.(consumer.ConsumerHandler) return handler.Handle(ctx, messageConsumeContext) } @@ -389,10 +408,14 @@ func (r *rabbitMQConsumer) runHandlersWithRetry( pipeValue := pipe nexValue := next - var handlerFunc pipeline.ConsumerHandlerFunc = func() error { + var handlerFunc pipeline.ConsumerHandlerFunc = func(ctx context.Context) error { genericContext, ok := messageConsumeContext.(messagingTypes.MessageConsumeContext) if ok { - return pipeValue.Handle(ctx, genericContext, nexValue) + return pipeValue.Handle( + ctx, + genericContext, + nexValue, + ) } return pipeValue.Handle( ctx, @@ -404,9 +427,12 @@ func (r *rabbitMQConsumer) runHandlersWithRetry( }) v := aggregateResult.(pipeline.ConsumerHandlerFunc) - err := v() + err := v(ctx) if err != nil { - return errors.Wrap(err, "error handling consumer handlers pipeline") + return errors.Wrap( + err, + "error handling consumer handlers pipeline", + ) } return nil } else { @@ -424,7 +450,11 @@ func (r *rabbitMQConsumer) runHandlersWithRetry( func (r *rabbitMQConsumer) createConsumeContext( delivery amqp091.Delivery, ) (messagingTypes.MessageConsumeContext, error) { - message := r.deserializeData(delivery.ContentType, delivery.Type, delivery.Body) + message := r.deserializeData( + delivery.ContentType, + delivery.Type, + delivery.Body, + ) if reflect.ValueOf(message).IsZero() || reflect.ValueOf(message).IsNil() { return *new(messagingTypes.MessageConsumeContext), errors.New( "error in deserialization of payload", @@ -482,7 +512,10 @@ func (r *rabbitMQConsumer) deserializeData( ) // or this to explicit type deserialization if err != nil { r.logger.Errorf( - fmt.Sprintf("error in deserilizng of type '%s' in the consumer", eventType), + fmt.Sprintf( + "error in deserilizng of type '%s' in the consumer", + eventType, + ), ) return nil } diff --git a/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go b/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go index 4ed61939..323157d2 100644 --- a/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go +++ b/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go @@ -4,114 +4,115 @@ import ( "context" "fmt" "testing" + "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/json" defaultLogger2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" messageConsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/pipeline" types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/bus" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" + rabbitmqConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/factory" + producerfactory "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/testcontainer/rabbitmq" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging/consumer" testUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/utils" - errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" uuid "github.com/satori/go.uuid" "github.com/stretchr/testify/require" ) -func Test_Consume_Message(t *testing.T) { +func Test_Consumer_With_Fake_Message(t *testing.T) { testUtils.SkipCI(t) - defer errorUtils.HandlePanic() ctx := context.Background() - eventSerializer := serializer.NewDefaultEventSerializer(json.NewDefaultSerializer()) - - tp, err := tracing.NewOtelTracing(&tracing.TracingOptions{ - ServiceName: "test", - Enabled: true, - AlwaysOnSampler: true, - ZipkinExporterOptions: &tracing.ZipkinExporterOptions{ - Url: "http://localhost:9411/api/v2/spans", - }, - }, environemnt.Development) + + //options := &config.RabbitmqOptions{ + // RabbitmqHostOptions: &config.RabbitmqHostOptions{ + // UserName: "guest", + // Password: "guest", + // HostName: "localhost", + // Port: 5672, + // }, + //} + + rabbitmqHostOption, err := rabbitmq.NewRabbitMQTestContainers(defaultLogger2.GetLogger()). + PopulateContainerOptions(ctx, t) require.NoError(t, err) - defer tp.Shutdown(ctx) + options := &config.RabbitmqOptions{ + RabbitmqHostOptions: rabbitmqHostOption, + } - conn, err := types.NewRabbitMQConnection(&config.RabbitmqOptions{ - RabbitmqHostOptions: &config.RabbitmqHostOptions{ - UserName: "guest", - Password: "guest", - HostName: "localhost", - Port: 5672, - }, - }) + conn, err := types.NewRabbitMQConnection(options) require.NoError(t, err) - fakeHandler := consumer.NewRabbitMQFakeTestConsumerHandler[ProducerConsumerMessage]() - builder := configurations.NewRabbitMQConsumerConfigurationBuilder(ProducerConsumerMessage{}) - builder.WithHandlers( - func(consumerHandlerBuilder messageConsumer.ConsumerHandlerConfigurationBuilder) { - consumerHandlerBuilder.AddHandler(NewTestMessageHandler()) - consumerHandlerBuilder.AddHandler(fakeHandler) - }, - ) - rabbitmqConsumer, err := NewRabbitMQConsumer( + eventSerializer := serializer.NewDefaultEventSerializer( + json.NewDefaultSerializer(), + ) + consumerFactory := factory.NewConsumerFactory( + options, + conn, + eventSerializer, + defaultLogger2.GetLogger(), + ) + producerFactory := producerfactory.NewProducerFactory( + options, conn, - builder.Build(), eventSerializer, defaultLogger2.GetLogger(), ) - require.NoError(t, err) - if rabbitmqConsumer == nil { - t.Log("RabbitMQ consumer is nil") - return - } - err = rabbitmqConsumer.Start(ctx) - if err != nil { - rabbitmqConsumer.Stop() - } - require.NoError(t, err) + fakeHandler := consumer.NewRabbitMQFakeTestConsumerHandler[ProducerConsumerMessage]() - rabbitmqProducer, err := producer.NewRabbitMQProducer( - conn, - nil, + rabbitmqBus, err := bus.NewRabbitmqBus( defaultLogger2.GetLogger(), - eventSerializer) + consumerFactory, + producerFactory, + func(builder rabbitmqConfigurations.RabbitMQConfigurationBuilder) { + builder.AddConsumer( + ProducerConsumerMessage{}, + func(consumerBuilder configurations.RabbitMQConsumerConfigurationBuilder) { + consumerBuilder.WithHandlers( + func(consumerHandlerBuilder messageConsumer.ConsumerHandlerConfigurationBuilder) { + consumerHandlerBuilder.AddHandler(fakeHandler) + }, + ) + }, + ) + }, + ) + + rabbitmqBus.Start(ctx) + defer rabbitmqBus.Stop() + + time.Sleep(time.Second * 1) + require.NoError(t, err) - //time.Sleep(time.Second * 5) - // - //fmt.Println("closing connection") - //conn.Close() - //fmt.Println(conn.IsClosed()) - // - //time.Sleep(time.Second * 10) - //fmt.Println("after 10 second of closing connection") - //fmt.Println(conn.IsClosed()) - - err = rabbitmqProducer.PublishMessage(ctx, NewProducerConsumerMessage("test"), nil) + err = rabbitmqBus.PublishMessage( + ctx, + NewProducerConsumerMessage("test"), + nil, + ) for err != nil { - err = rabbitmqProducer.PublishMessage(ctx, NewProducerConsumerMessage("test"), nil) + err = rabbitmqBus.PublishMessage( + ctx, + NewProducerConsumerMessage("test"), + nil, + ) } err = testUtils.WaitUntilConditionMet(func() bool { return fakeHandler.IsHandled() }) - require.NoError(t, err) - - rabbitmqConsumer.Stop() - conn.Close() - fmt.Println(conn.IsClosed()) - fmt.Println(conn.IsConnected()) + require.NoError(t, err) } type ProducerConsumerMessage struct { @@ -174,10 +175,13 @@ func (p Pipeline1) Handle( fmt.Println("PipelineBehaviourTest.Handled") fmt.Println( - fmt.Sprintf("pipeline got a message with id '%s'", consumerContext.Message().GeMessageId()), + fmt.Sprintf( + "pipeline got a message with id '%s'", + consumerContext.Message().GeMessageId(), + ), ) - err := next() + err := next(ctx) if err != nil { return err } diff --git a/internal/pkg/rabbitmq/producer/producer_factory.go b/internal/pkg/rabbitmq/producer/producer_factory.go new file mode 100644 index 00000000..e2f324ce --- /dev/null +++ b/internal/pkg/rabbitmq/producer/producer_factory.go @@ -0,0 +1,46 @@ +package producer + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" + producerConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/configurations" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/producercontracts" + types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" +) + +type producerFactory struct { + connection types2.IConnection + logger logger.Logger + eventSerializer serializer.EventSerializer + rabbitmqOptions *config.RabbitmqOptions +} + +func NewProducerFactory( + rabbitmqOptions *config.RabbitmqOptions, + connection types2.IConnection, + eventSerializer serializer.EventSerializer, + l logger.Logger, +) producercontracts.ProducerFactory { + return &producerFactory{ + rabbitmqOptions: rabbitmqOptions, + logger: l, + connection: connection, + eventSerializer: eventSerializer, + } +} + +func (p *producerFactory) CreateProducer( + rabbitmqProducersConfiguration map[string]*producerConfigurations.RabbitMQProducerConfiguration, + isProducedNotifications ...func(message types.IMessage), +) (producer.Producer, error) { + return NewRabbitMQProducer( + p.rabbitmqOptions, + p.connection, + rabbitmqProducersConfiguration, + p.logger, + p.eventSerializer, + isProducedNotifications...) +} diff --git a/internal/pkg/rabbitmq/producer/producercontracts/producer_factory.go b/internal/pkg/rabbitmq/producer/producercontracts/producer_factory.go new file mode 100644 index 00000000..f407b881 --- /dev/null +++ b/internal/pkg/rabbitmq/producer/producercontracts/producer_factory.go @@ -0,0 +1,14 @@ +package producercontracts + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" + types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/configurations" +) + +type ProducerFactory interface { + CreateProducer( + rabbitmqProducersConfiguration map[string]*configurations.RabbitMQProducerConfiguration, + isProducedNotifications ...func(message types2.IMessage), + ) (producer.Producer, error) +} diff --git a/internal/pkg/rabbitmq/producer/rabbitmq_producer.go b/internal/pkg/rabbitmq/producer/rabbitmq_producer.go index b9c864f3..131a5f1a 100644 --- a/internal/pkg/rabbitmq/producer/rabbitmq_producer.go +++ b/internal/pkg/rabbitmq/producer/rabbitmq_producer.go @@ -13,6 +13,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/utils" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" @@ -26,6 +27,7 @@ import ( type rabbitMQProducer struct { logger logger.Logger + rabbitmqOptions *config.RabbitmqOptions connection types.IConnection eventSerializer serializer.EventSerializer producersConfigurations map[string]*configurations.RabbitMQProducerConfiguration @@ -33,6 +35,7 @@ type rabbitMQProducer struct { } func NewRabbitMQProducer( + cfg *config.RabbitmqOptions, connection types.IConnection, rabbitmqProducersConfiguration map[string]*configurations.RabbitMQProducerConfiguration, logger logger.Logger, @@ -41,6 +44,7 @@ func NewRabbitMQProducer( ) (producer.Producer, error) { p := &rabbitMQProducer{ logger: logger, + rabbitmqOptions: cfg, connection: connection, eventSerializer: eventSerializer, producersConfigurations: rabbitmqProducersConfiguration, @@ -88,7 +92,9 @@ func (r *rabbitMQProducer) PublishMessageWithTopicName( producerConfiguration := r.getProducerConfigurationByMessage(message) if producerConfiguration == nil { - producerConfiguration = configurations.NewDefaultRabbitMQProducerConfiguration(message) + producerConfiguration = configurations.NewDefaultRabbitMQProducerConfiguration( + message, + ) } var exchange string @@ -134,7 +140,10 @@ func (r *rabbitMQProducer) PublishMessageWithTopicName( // https://github.com/rabbitmq/rabbitmq-tutorials/blob/master/go/publisher_confirms.go if r.connection == nil { - return producer2.FinishProducerSpan(beforeProduceSpan, errors.New("connection is nil")) + return producer2.FinishProducerSpan( + beforeProduceSpan, + errors.New("connection is nil"), + ) } if r.connection.IsClosed() { @@ -192,7 +201,10 @@ func (r *rabbitMQProducer) PublishMessageWithTopicName( } if confirmed := <-confirms; !confirmed.Ack { - return producer2.FinishProducerSpan(beforeProduceSpan, errors.New("ack not confirmed")) + return producer2.FinishProducerSpan( + beforeProduceSpan, + errors.New("ack not confirmed"), + ) } if len(r.isProducedNotifications) > 0 { diff --git a/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go b/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go index a2c2c4d4..73867303 100644 --- a/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go +++ b/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/json" defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" @@ -35,29 +35,44 @@ func Test_Publish_Message(t *testing.T) { Url: "http://localhost:9411/api/v2/spans", }, }, - environemnt.Development, + environment.Development, ) if err != nil { return } defer tp.Shutdown(ctx) - conn, err := types.NewRabbitMQConnection(&config.RabbitmqOptions{ + //conn, err := types.NewRabbitMQConnection(&config.RabbitmqOptions{ + // RabbitmqHostOptions: &config.RabbitmqHostOptions{ + // UserName: "guest", + // Password: "guest", + // HostName: "localhost", + // Port: 5672, + // }, + //}) + //require.NoError(t, err) + + options := &config.RabbitmqOptions{ RabbitmqHostOptions: &config.RabbitmqHostOptions{ UserName: "guest", Password: "guest", HostName: "localhost", Port: 5672, }, - }) + } + + conn, err := types.NewRabbitMQConnection(options) require.NoError(t, err) - rabbitmqProducer, err := NewRabbitMQProducer( + producerFactory := NewProducerFactory( + options, conn, - nil, - defaultLogger.GetLogger(), eventSerializer, + defaultLogger.GetLogger(), ) + + rabbitmqProducer, err := producerFactory.CreateProducer(nil) + require.NoError(t, err) err = rabbitmqProducer.PublishMessage(ctx, NewProducerMessage("test"), nil) diff --git a/internal/pkg/rabbitmq/rabbitmq_fx.go b/internal/pkg/rabbitmq/rabbitmq_fx.go index 4ad35003..c966fc4e 100644 --- a/internal/pkg/rabbitmq/rabbitmq_fx.go +++ b/internal/pkg/rabbitmq/rabbitmq_fx.go @@ -11,6 +11,8 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/bus" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/factory" + producer2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" "go.uber.org/fx" @@ -37,11 +39,13 @@ var ( fx.Provide(types.NewRabbitMQConnection), fx.Provide(fx.Annotate( bus.NewRabbitmqBus, - fx.ParamTags(``, ``, ``, ``, `optional:"true"`), + fx.ParamTags(``, ``, ``, `optional:"true"`), fx.As(new(producer.Producer)), fx.As(new(bus2.Bus)), fx.As(new(bus.RabbitmqBus)), )), + fx.Provide(factory.NewConsumerFactory), + fx.Provide(producer2.NewProducerFactory), fx.Provide(fx.Annotate( NewRabbitMQHealthChecker, fx.As(new(contracts.Health)), @@ -52,7 +56,9 @@ var ( // - they execute by their orders // - invokes always execute its func compare to provides that only run when we request for them. // - return value will be discarded and can not be provided - rabbitmqInvokes = fx.Options(fx.Invoke(registerHooks)) //nolint:gochecknoglobals + rabbitmqInvokes = fx.Options( + fx.Invoke(registerHooks), + ) //nolint:gochecknoglobals ) // we don't want to register any dependencies here, its func body should execute always even we don't request for that, so we should use `invoke` @@ -77,7 +83,10 @@ func registerHooks( go func() { // if (ctx.Err() == nil), context not canceled or deadlined if err := bus.Start(lifeTimeCtx); err != nil { - logger.Errorf("(bus.Start) error in running rabbitmq server: {%v}", err) + logger.Errorf( + "(bus.Start) error in running rabbitmq server: {%v}", + err, + ) return } }() diff --git a/internal/pkg/rabbitmq/test/testcontainer/rabbitmq_test_container.go b/internal/pkg/rabbitmq/test/testcontainer/rabbitmq_test_container.go new file mode 100644 index 00000000..5a59d745 --- /dev/null +++ b/internal/pkg/rabbitmq/test/testcontainer/rabbitmq_test_container.go @@ -0,0 +1,95 @@ +package testcontainer + +import ( + "context" + "fmt" + "testing" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" + + "github.com/docker/docker/api/types/container" + "github.com/docker/go-connections/nat" + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" +) + +func CreatingContainerOptions( + ctx context.Context, + t *testing.T, +) (*config.RabbitmqHostOptions, error) { + t.Helper() + + // https://github.com/testcontainers/testcontainers-go + // https://dev.to/remast/go-integration-tests-using-testcontainers-9o5 + containerReq := testcontainers.ContainerRequest{ + Image: fmt.Sprintf( + "%s:%s", + "rabbitmq", + "management", + ), + ExposedPorts: []string{"5672/tcp", "15672/tcp"}, + WaitingFor: wait.ForListeningPort( + nat.Port("5672/tcp"), + ), + HostConfigModifier: func(hostConfig *container.HostConfig) { + hostConfig.AutoRemove = true + }, + Hostname: "localhost", + Env: map[string]string{ + "RABBITMQ_DEFAULT_USER": "guest", + "RABBITMQ_DEFAULT_PASS": "guest", + }, + } + + dbContainer, err := testcontainers.GenericContainer( + context.Background(), + testcontainers.GenericContainerRequest{ + ContainerRequest: containerReq, + Started: true, + }) + if err != nil { + return nil, err + } + + //// Clean up the container after the test is complete + t.Cleanup(func() { + if terr := dbContainer.Terminate(ctx); terr != nil { + t.Fatalf("failed to terminate container: %s", err) + } + }) + + // get a free random host port for rabbitmq `Tcp Port` + hostPort, err := dbContainer.MappedPort( + ctx, + nat.Port("5672/tcp"), + ) + if err != nil { + return nil, err + } + + // https://github.com/michaelklishin/rabbit-hole/issues/74 + // get a free random host port for rabbitmq UI `Http Port` + uiHttpPort, err := dbContainer.MappedPort( + ctx, + nat.Port("15672/tcp"), + ) + if err != nil { + return nil, err + } + + host, err := dbContainer.Host(ctx) + if err != nil { + return nil, err + } + + option := &config.RabbitmqHostOptions{ + UserName: "guest", + Password: "guest", + HostName: host, + VirtualHost: "/", + Port: hostPort.Int(), + HttpPort: uiHttpPort.Int(), + } + + return option, nil +} diff --git a/internal/pkg/redis/redis_options.go b/internal/pkg/redis/redis_options.go index 5d0fecef..7cb2ee3c 100644 --- a/internal/pkg/redis/redis_options.go +++ b/internal/pkg/redis/redis_options.go @@ -2,7 +2,7 @@ package redis import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" "github.com/iancoleman/strcase" @@ -19,6 +19,6 @@ type RedisOptions struct { EnableTracing bool `mapstructure:"enableTracing" default:"true"` } -func provideConfig(environment environemnt.Environment) (*RedisOptions, error) { +func provideConfig(environment environment.Environment) (*RedisOptions, error) { return config.BindConfigKey[*RedisOptions](optionName, environment) } diff --git a/internal/pkg/test/containers/contracts/eventstoredb_container.go b/internal/pkg/test/containers/contracts/eventstoredb_container.go index aa6aa36c..39a52e4f 100644 --- a/internal/pkg/test/containers/contracts/eventstoredb_container.go +++ b/internal/pkg/test/containers/contracts/eventstoredb_container.go @@ -5,8 +5,6 @@ import ( "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/eventstroredb/config" - - "github.com/EventStore/EventStore-Client-Go/esdb" ) type EventstoreDBContainerOptions struct { @@ -21,15 +19,11 @@ type EventstoreDBContainerOptions struct { } type EventstoreDBContainer interface { - CreatingContainerOptions( + PopulateContainerOptions( ctx context.Context, t *testing.T, options ...*EventstoreDBContainerOptions, ) (*config.EventStoreDbOptions, error) - Start(ctx context.Context, - t *testing.T, - options ...*EventstoreDBContainerOptions) (*esdb.Client, error) - Cleanup(ctx context.Context) error } diff --git a/internal/pkg/test/containers/contracts/gorm_container.go b/internal/pkg/test/containers/contracts/gorm_container.go index a96bdfc2..18f14664 100644 --- a/internal/pkg/test/containers/contracts/gorm_container.go +++ b/internal/pkg/test/containers/contracts/gorm_container.go @@ -5,8 +5,6 @@ import ( "testing" gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" - - "gorm.io/gorm" ) type PostgresContainerOptions struct { @@ -22,8 +20,7 @@ type PostgresContainerOptions struct { } type GormContainer interface { - Start(ctx context.Context, t *testing.T, options ...*PostgresContainerOptions) (*gorm.DB, error) - CreatingContainerOptions( + PopulateContainerOptions( ctx context.Context, t *testing.T, options ...*PostgresContainerOptions, diff --git a/internal/pkg/test/containers/contracts/mongo_container.go b/internal/pkg/test/containers/contracts/mongo_container.go index b7b9622e..67314820 100644 --- a/internal/pkg/test/containers/contracts/mongo_container.go +++ b/internal/pkg/test/containers/contracts/mongo_container.go @@ -5,8 +5,6 @@ import ( "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" - - "go.mongodb.org/mongo-driver/mongo" ) type MongoContainerOptions struct { @@ -22,12 +20,7 @@ type MongoContainerOptions struct { } type MongoContainer interface { - Start( - ctx context.Context, - t *testing.T, - options ...*MongoContainerOptions, - ) (*mongo.Client, error) - CreatingContainerOptions( + PopulateContainerOptions( ctx context.Context, t *testing.T, options ...*MongoContainerOptions, diff --git a/internal/pkg/test/containers/contracts/postgrespgx_container.go b/internal/pkg/test/containers/contracts/postgrespgx_container.go index 7d1bd432..b7267258 100644 --- a/internal/pkg/test/containers/contracts/postgrespgx_container.go +++ b/internal/pkg/test/containers/contracts/postgrespgx_container.go @@ -8,8 +8,7 @@ import ( ) type PostgresPgxContainer interface { - Start(ctx context.Context, t *testing.T, options ...*PostgresContainerOptions) (*postgres.Pgx, error) - CreatingContainerOptions( + PopulateContainerOptions( ctx context.Context, t *testing.T, options ...*PostgresContainerOptions, diff --git a/internal/pkg/test/containers/contracts/rabbitmq_container.go b/internal/pkg/test/containers/contracts/rabbitmq_container.go index 5f012fa5..ca6c62ab 100644 --- a/internal/pkg/test/containers/contracts/rabbitmq_container.go +++ b/internal/pkg/test/containers/contracts/rabbitmq_container.go @@ -5,10 +5,7 @@ import ( "fmt" "testing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/bus" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" ) type RabbitMQContainerOptions struct { @@ -25,7 +22,13 @@ type RabbitMQContainerOptions struct { } func (h *RabbitMQContainerOptions) AmqpEndPoint() string { - return fmt.Sprintf("amqp://%s:%s@%s:%d", h.UserName, h.Password, h.Host, h.HostPort) + return fmt.Sprintf( + "amqp://%s:%s@%s:%d", + h.UserName, + h.Password, + h.Host, + h.HostPort, + ) } func (h *RabbitMQContainerOptions) HttpEndPoint() string { @@ -33,13 +36,7 @@ func (h *RabbitMQContainerOptions) HttpEndPoint() string { } type RabbitMQContainer interface { - Start(ctx context.Context, - t *testing.T, - serializer serializer.EventSerializer, - rabbitmqBuilderFunc configurations.RabbitMQConfigurationBuilderFuc, - options ...*RabbitMQContainerOptions) (bus.Bus, error) - - CreatingContainerOptions( + PopulateContainerOptions( ctx context.Context, t *testing.T, options ...*RabbitMQContainerOptions, diff --git a/internal/pkg/test/containers/contracts/redis_container.go b/internal/pkg/test/containers/contracts/redis_container.go index f44cbfe6..a6d0c0b3 100644 --- a/internal/pkg/test/containers/contracts/redis_container.go +++ b/internal/pkg/test/containers/contracts/redis_container.go @@ -5,8 +5,6 @@ import ( "testing" redis2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/redis" - - "github.com/redis/go-redis/v9" ) type RedisContainerOptions struct { @@ -21,12 +19,7 @@ type RedisContainerOptions struct { } type RedisContainer interface { - Start( - ctx context.Context, - t *testing.T, - options ...*RedisContainerOptions, - ) (redis.UniversalClient, error) - CreatingContainerOptions( + PopulateContainerOptions( ctx context.Context, t *testing.T, options ...*RedisContainerOptions, diff --git a/internal/pkg/test/containers/dockertest/gorm/gorm_container.go b/internal/pkg/test/containers/dockertest/gorm/gorm_container.go index d1d8912e..15584d43 100644 --- a/internal/pkg/test/containers/dockertest/gorm/gorm_container.go +++ b/internal/pkg/test/containers/dockertest/gorm/gorm_container.go @@ -12,7 +12,6 @@ import ( "github.com/ory/dockertest/v3" "github.com/ory/dockertest/v3/docker" "github.com/phayes/freeport" - "gorm.io/gorm" ) type gormDockerTest struct { @@ -35,11 +34,13 @@ func NewGormDockerTest() contracts.GormContainer { } } -func (g *gormDockerTest) CreatingContainerOptions( +func (g *gormDockerTest) PopulateContainerOptions( ctx context.Context, t *testing.T, options ...*contracts.PostgresContainerOptions, ) (*gormPostgres.GormOptions, error) { + t.Helper() + // https://github.com/ory/dockertest/blob/v3/examples/PostgreSQL.md // https://github.com/bozd4g/fb.testcontainers pool, err := dockertest.NewPool("") @@ -57,7 +58,10 @@ func (g *gormDockerTest) CreatingContainerOptions( config.RestartPolicy = docker.RestartPolicy{Name: "no"} }) if err != nil { - log.Fatalf("Could not start resource (Postgresql Test Container): %s", err) + log.Fatalf( + "Could not start resource (Postgresql Test Container): %s", + err, + ) } resource.Expire( @@ -91,21 +95,6 @@ func (g *gormDockerTest) CreatingContainerOptions( return postgresoptions, nil } -func (g *gormDockerTest) Start( - ctx context.Context, - t *testing.T, - options ...*contracts.PostgresContainerOptions, -) (*gorm.DB, error) { - gormOptions, err := g.CreatingContainerOptions(ctx, t, options...) - if err != nil { - return nil, err - } - - db, err := gormPostgres.NewGorm(gormOptions) - - return db, nil -} - func (g *gormDockerTest) Cleanup(ctx context.Context) error { return g.resource.Close() } @@ -154,7 +143,10 @@ func (g *gormDockerTest) getRunOptions( ExposedPorts: []string{g.defaultOptions.Port}, PortBindings: map[docker.Port][]docker.PortBinding{ docker.Port(g.defaultOptions.Port): { - {HostIP: "0.0.0.0", HostPort: strconv.Itoa(g.defaultOptions.HostPort)}, + { + HostIP: "0.0.0.0", + HostPort: strconv.Itoa(g.defaultOptions.HostPort), + }, }, }, } diff --git a/internal/pkg/test/containers/dockertest/gorm/gorm_container_test.go b/internal/pkg/test/containers/dockertest/gorm/gorm_container_test.go index ebee5aba..8e5ce2dd 100644 --- a/internal/pkg/test/containers/dockertest/gorm/gorm_container_test.go +++ b/internal/pkg/test/containers/dockertest/gorm/gorm_container_test.go @@ -4,12 +4,32 @@ import ( "context" "testing" - "github.com/stretchr/testify/require" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" + + "github.com/stretchr/testify/assert" + "go.uber.org/fx" + "go.uber.org/fx/fxtest" + "gorm.io/gorm" ) func Test_Gorm_Container(t *testing.T) { - gorm, err := NewGormDockerTest().Start(context.Background(), t) - require.NoError(t, err) + ctx := context.Background() + var gorm *gorm.DB + + fxtest.New(t, + config.ModuleFunc(environment.Test), + zap.Module, + fxlog.FxLogger, + core.Module, + gormPostgres.Module, + fx.Decorate(GormDockerTestConatnerOptionsDecorator(t, ctx)), + fx.Populate(&gorm), + ).RequireStart() - require.NotNil(t, gorm) + assert.NotNil(t, gorm) } diff --git a/internal/pkg/test/containers/dockertest/gorm/gorm_fx.go b/internal/pkg/test/containers/dockertest/gorm/gorm_fx.go new file mode 100644 index 00000000..0e888dfd --- /dev/null +++ b/internal/pkg/test/containers/dockertest/gorm/gorm_fx.go @@ -0,0 +1,14 @@ +package gorm + +import ( + "context" + "testing" + + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" +) + +var GormDockerTestConatnerOptionsDecorator = func(t *testing.T, ctx context.Context) interface{} { + return func(c *gormPostgres.GormOptions) (*gormPostgres.GormOptions, error) { + return NewGormDockerTest().PopulateContainerOptions(ctx, t) + } +} diff --git a/internal/pkg/test/containers/dockertest/mongo/mongo_container.go b/internal/pkg/test/containers/dockertest/mongo/mongo_container.go index 0fa6683c..3c90ab8c 100644 --- a/internal/pkg/test/containers/dockertest/mongo/mongo_container.go +++ b/internal/pkg/test/containers/dockertest/mongo/mongo_container.go @@ -12,7 +12,6 @@ import ( "github.com/ory/dockertest/v3" "github.com/ory/dockertest/v3/docker" - "go.mongodb.org/mongo-driver/mongo" ) type mongoDockerTest struct { @@ -35,7 +34,7 @@ func NewMongoDockerTest() contracts.MongoContainer { } } -func (g *mongoDockerTest) CreatingContainerOptions( +func (g *mongoDockerTest) PopulateContainerOptions( ctx context.Context, t *testing.T, options ...*contracts.MongoContainerOptions, @@ -48,13 +47,16 @@ func (g *mongoDockerTest) CreatingContainerOptions( runOptions := g.getRunOptions(options...) // pull mongodb docker image for version 5.0 - resource, err := pool.RunWithOptions(runOptions, func(config *docker.HostConfig) { - // set AutoRemove to true so that stopped container goes away by itself - config.AutoRemove = true - config.RestartPolicy = docker.RestartPolicy{ - Name: "no", - } - }) + resource, err := pool.RunWithOptions( + runOptions, + func(config *docker.HostConfig) { + // set AutoRemove to true so that stopped container goes away by itself + config.AutoRemove = true + config.RestartPolicy = docker.RestartPolicy{ + Name: "no", + } + }, + ) if err != nil { log.Fatalf("Could not start resource (Mongo Container): %s", err) } @@ -64,7 +66,9 @@ func (g *mongoDockerTest) CreatingContainerOptions( ) // Tell docker to hard kill the container in 120 seconds exponential backoff-retry, because the application_exceptions in the container might not be ready to accept connections yet g.resource = resource - port, _ := strconv.Atoi(resource.GetPort(fmt.Sprintf("%s/tcp", g.defaultOptions.Port))) + port, _ := strconv.Atoi( + resource.GetPort(fmt.Sprintf("%s/tcp", g.defaultOptions.Port)), + ) g.defaultOptions.HostPort = port t.Cleanup(func() { _ = resource.Close() }) @@ -91,24 +95,6 @@ func (g *mongoDockerTest) CreatingContainerOptions( return mongoOptions, nil } -func (g *mongoDockerTest) Start( - ctx context.Context, - t *testing.T, - options ...*contracts.MongoContainerOptions, -) (*mongo.Client, error) { - mongoOptions, err := g.CreatingContainerOptions(ctx, t, options...) - if err != nil { - return nil, err - } - - db, err := mongodb.NewMongoDB(mongoOptions) - if err != nil { - return nil, err - } - - return db, nil -} - func (g *mongoDockerTest) Cleanup(ctx context.Context) error { return g.resource.Close() } diff --git a/internal/pkg/test/containers/dockertest/mongo/mongo_container_test.go b/internal/pkg/test/containers/dockertest/mongo/mongo_container_test.go index 519305ef..c4d4282f 100644 --- a/internal/pkg/test/containers/dockertest/mongo/mongo_container_test.go +++ b/internal/pkg/test/containers/dockertest/mongo/mongo_container_test.go @@ -4,13 +4,32 @@ import ( "context" "testing" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" + "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + "go.mongodb.org/mongo-driver/mongo" + "go.uber.org/fx" + "go.uber.org/fx/fxtest" ) func Test_Mongo_Container(t *testing.T) { - mongo, err := NewMongoDockerTest().Start(context.Background(), t) - require.NoError(t, err) + ctx := context.Background() + var mongoClient *mongo.Client + + fxtest.New(t, + config.ModuleFunc(environment.Test), + zap.Module, + fxlog.FxLogger, + core.Module, + mongodb.Module, + fx.Decorate(MongoDockerTestContainerOptionsDecorator(t, ctx)), + fx.Populate(&mongoClient), + ).RequireStart() - assert.NotNil(t, mongo) + assert.NotNil(t, mongoClient) } diff --git a/internal/pkg/test/containers/dockertest/mongo/mongo_fx.go b/internal/pkg/test/containers/dockertest/mongo/mongo_fx.go new file mode 100644 index 00000000..79763bc1 --- /dev/null +++ b/internal/pkg/test/containers/dockertest/mongo/mongo_fx.go @@ -0,0 +1,15 @@ +package mongo + +import ( + "context" + "testing" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" +) + +var MongoDockerTestContainerOptionsDecorator = func(t *testing.T, ctx context.Context) interface{} { + return func(c *mongodb.MongoDbOptions, logger logger.Logger) (*mongodb.MongoDbOptions, error) { + return NewMongoDockerTest().PopulateContainerOptions(ctx, t) + } +} diff --git a/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_container.go b/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_container.go index 423412df..25d3c36c 100644 --- a/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_container.go +++ b/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_container.go @@ -7,13 +7,8 @@ import ( "strconv" "testing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/bus" - bus2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/bus" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/contracts" "github.com/ory/dockertest/v3" @@ -29,11 +24,6 @@ type rabbitmqDockerTest struct { } func NewRabbitMQDockerTest(logger logger.Logger) contracts.RabbitMQContainer { - pool, err := dockertest.NewPool("") - if err != nil { - log.Fatalf("Could not connect to docker: %s", err) - } - return &rabbitmqDockerTest{ defaultOptions: &contracts.RabbitMQContainerOptions{ Ports: []string{"5672", "15672"}, @@ -46,25 +36,32 @@ func NewRabbitMQDockerTest(logger logger.Logger) contracts.RabbitMQContainer { Name: "rabbitmq-dockertest", }, logger: logger, - pool: pool, } } -func (g *rabbitmqDockerTest) CreatingContainerOptions( +func (g *rabbitmqDockerTest) PopulateContainerOptions( ctx context.Context, t *testing.T, options ...*contracts.RabbitMQContainerOptions, ) (*config.RabbitmqHostOptions, error) { + pool, err := dockertest.NewPool("") + if err != nil { + log.Fatalf("Could not connect to docker: %s", err) + } + runOptions := g.getRunOptions(options...) // pull mongodb docker image for version 5.0 - resource, err := g.pool.RunWithOptions(runOptions, func(config *docker.HostConfig) { - // set AutoRemove to true so that stopped container goes away by itself - config.AutoRemove = true - config.RestartPolicy = docker.RestartPolicy{ - Name: "no", - } - }) + resource, err := pool.RunWithOptions( + runOptions, + func(config *docker.HostConfig) { + // set AutoRemove to true so that stopped container goes away by itself + config.AutoRemove = true + config.RestartPolicy = docker.RestartPolicy{ + Name: "no", + } + }, + ) if err != nil { log.Fatalf("Could not start resource (RabbitMQ Container): %s", err) } @@ -86,62 +83,29 @@ func (g *rabbitmqDockerTest) CreatingContainerOptions( t.Cleanup(func() { _ = resource.Close() }) - isConnectable := isConnectable(g.logger, g.defaultOptions) - if !isConnectable { - return g.CreatingContainerOptions(context.Background(), t, options...) - } - - opt := &config.RabbitmqHostOptions{ - UserName: g.defaultOptions.UserName, - Password: g.defaultOptions.Password, - HostName: g.defaultOptions.Host, - VirtualHost: g.defaultOptions.VirtualHost, - Port: g.defaultOptions.HostPort, - HttpPort: g.defaultOptions.HttpPort, - } - - return opt, nil -} - -func (g *rabbitmqDockerTest) Start( - ctx context.Context, - t *testing.T, - serializer serializer.EventSerializer, - rabbitmqBuilderFunc configurations.RabbitMQConfigurationBuilderFuc, - options ...*contracts.RabbitMQContainerOptions, -) (bus.Bus, error) { - rabbitmqHostOptions, err := g.CreatingContainerOptions(ctx, t, options...) - if err != nil { - return nil, err - } - - var mqBus bus.Bus - if err := g.pool.Retry(func() error { - config := &config.RabbitmqOptions{ - RabbitmqHostOptions: rabbitmqHostOptions, - } - conn, err := types.NewRabbitMQConnection(config) - if err != nil { - return err - } - - mqBus, err = bus2.NewRabbitmqBus( - config, - serializer, - g.logger, - conn, - rabbitmqBuilderFunc) - if err != nil { - return err + //isConnectable := isConnectable(g.logger, g.defaultOptions) + //if !isConnectable { + // return g.PopulateContainerOptions(context.Background(), t, options...) + //} + + var rabbitmqoptions *config.RabbitmqHostOptions + if err = pool.Retry(func() error { + rabbitmqoptions = &config.RabbitmqHostOptions{ + UserName: g.defaultOptions.UserName, + Password: g.defaultOptions.Password, + HostName: g.defaultOptions.Host, + VirtualHost: g.defaultOptions.VirtualHost, + Port: g.defaultOptions.HostPort, + HttpPort: g.defaultOptions.HttpPort, } return nil }); err != nil { - g.logger.Errorf("Could not connect to docker: %s", err) + log.Fatalf("Could not connect to docker: %s", err) return nil, err } - return mqBus, nil + return rabbitmqoptions, nil } func (g *rabbitmqDockerTest) Cleanup(ctx context.Context) error { @@ -187,12 +151,27 @@ func (g *rabbitmqDockerTest) getRunOptions( return runOptions } -func isConnectable(logger logger.Logger, options *contracts.RabbitMQContainerOptions) bool { +func isConnectable( + logger logger.Logger, + options *contracts.RabbitMQContainerOptions, +) bool { conn, err := amqp091.Dial( - fmt.Sprintf("amqp://%s:%s@%s:%d", options.UserName, options.Password, options.Host, options.HostPort), + fmt.Sprintf( + "amqp://%s:%s@%s:%d", + options.UserName, + options.Password, + options.Host, + options.HostPort, + ), ) if err != nil { - logError(logger, options.UserName, options.Password, options.Host, options.HostPort) + logError( + logger, + options.UserName, + options.Password, + options.Host, + options.HostPort, + ) return false } @@ -200,24 +179,48 @@ func isConnectable(logger logger.Logger, options *contracts.RabbitMQContainerOpt defer conn.Close() if err != nil || (conn != nil && conn.IsClosed()) { - logError(logger, options.UserName, options.Password, options.Host, options.HostPort) + logError( + logger, + options.UserName, + options.Password, + options.Host, + options.HostPort, + ) return false } logger.Infof( "Opened rabbitmq connection on host: %s", - fmt.Sprintf("amqp://%s:%s@%s:%d", options.UserName, options.Password, options.Host, options.HostPort), + fmt.Sprintf( + "amqp://%s:%s@%s:%d", + options.UserName, + options.Password, + options.Host, + options.HostPort, + ), ) return true } -func logError(logger logger.Logger, userName string, password string, host string, hostPort int) { +func logError( + logger logger.Logger, + userName string, + password string, + host string, + hostPort int, +) { // we should not use `t.Error` or `t.Errorf` for logging errors because it will `fail` our test at the end and, we just should use logs without error like log.Error (not log.Fatal) logger.Errorf( fmt.Sprintf( "Error in creating rabbitmq connection with %s", - fmt.Sprintf("amqp://%s:%s@%s:%d", userName, password, host, hostPort), + fmt.Sprintf( + "amqp://%s:%s@%s:%d", + userName, + password, + host, + hostPort, + ), ), ) } diff --git a/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_container_test.go b/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_container_test.go index 0278cc2e..414b51cd 100644 --- a/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_container_test.go +++ b/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_container_test.go @@ -5,11 +5,17 @@ import ( "testing" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/json" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/bus" messageConsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + rabbitmq2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" rabbitmqConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" consumerConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging/consumer" @@ -17,36 +23,50 @@ import ( uuid "github.com/satori/go.uuid" "github.com/stretchr/testify/require" + "go.uber.org/fx" + "go.uber.org/fx/fxtest" ) func Test_RabbitMQ_Container(t *testing.T) { ctx := context.Background() fakeConsumer := consumer.NewRabbitMQFakeTestConsumerHandler[*ProducerConsumerMessage]() - eventSerializer := serializer.NewDefaultEventSerializer(json.NewDefaultSerializer()) - rabbitmq, err := NewRabbitMQDockerTest( - defaultLogger.GetLogger(), - ).Start(ctx, t, eventSerializer, func(builder rabbitmqConfigurations.RabbitMQConfigurationBuilder) { - builder.AddConsumer(ProducerConsumerMessage{}, - func(consumerBuilder consumerConfigurations.RabbitMQConsumerConfigurationBuilder) { - consumerBuilder.WithHandlers( - func(handlerBuilder messageConsumer.ConsumerHandlerConfigurationBuilder) { - handlerBuilder.AddHandler(fakeConsumer) - }, - ) - }) - }) + var rabbitmqbus bus.Bus - require.NoError(t, err) - require.NotNil(t, rabbitmq) + fxtest.New(t, + config.ModuleFunc(environment.Test), + zap.Module, + fxlog.FxLogger, + core.Module, + rabbitmq2.ModuleFunc( + func(l logger.Logger) rabbitmqConfigurations.RabbitMQConfigurationBuilderFuc { + return func(builder configurations.RabbitMQConfigurationBuilder) { + builder.AddConsumer( + ProducerConsumerMessage{}, + func(consumerBuilder consumerConfigurations.RabbitMQConsumerConfigurationBuilder) { + consumerBuilder.WithHandlers( + func(handlerBuilder messageConsumer.ConsumerHandlerConfigurationBuilder) { + handlerBuilder.AddHandler(fakeConsumer) + }, + ) + }, + ) + } + }, + ), + fx.Decorate(RabbitmqDockerTestContainerOptionsDecorator(t, ctx)), + fx.Populate(&rabbitmqbus), + ).RequireStart() + + require.NotNil(t, rabbitmqbus) - err = rabbitmq.Start(ctx) + err := rabbitmqbus.Start(ctx) require.NoError(t, err) - // wait for consumers ready to consume before publishing messages (for preventing messages lost) - time.Sleep(time.Second * 1) + //// wait for consumers ready to consume before publishing messages (for preventing messages lost) + time.Sleep(time.Second * 2) - err = rabbitmq.PublishMessage( + err = rabbitmqbus.PublishMessage( context.Background(), &ProducerConsumerMessage{ Data: "ssssssssss", diff --git a/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_fx.go b/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_fx.go index 7cf7af6b..73311f36 100644 --- a/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_fx.go +++ b/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_fx.go @@ -10,7 +10,7 @@ import ( var RabbitmqDockerTestContainerOptionsDecorator = func(t *testing.T, ctx context.Context) interface{} { return func(c *config.RabbitmqOptions, logger logger.Logger) (*config.RabbitmqOptions, error) { - rabbitmqHostOptions, err := NewRabbitMQDockerTest(logger).CreatingContainerOptions(ctx, t) + rabbitmqHostOptions, err := NewRabbitMQDockerTest(logger).PopulateContainerOptions(ctx, t) c.RabbitmqHostOptions = rabbitmqHostOptions return c, err diff --git a/internal/pkg/test/containers/gnomock/gorm/gorm_container.go b/internal/pkg/test/containers/gnomock/gorm/gorm_container.go index 91292a0a..2c504f67 100644 --- a/internal/pkg/test/containers/gnomock/gorm/gorm_container.go +++ b/internal/pkg/test/containers/gnomock/gorm/gorm_container.go @@ -34,7 +34,7 @@ func NewGnoMockGormContainer() contracts.GormContainer { } } -func (g *gnoMockGormContainer) CreatingContainerOptions( +func (g *gnoMockGormContainer) PopulateContainerOptions( ctx context.Context, t *testing.T, options ...*contracts.PostgresContainerOptions, @@ -70,7 +70,7 @@ func (g *gnoMockGormContainer) Start( t *testing.T, options ...*contracts.PostgresContainerOptions, ) (*gorm.DB, error) { - gormOptions, err := g.CreatingContainerOptions(ctx, t, options...) + gormOptions, err := g.PopulateContainerOptions(ctx, t, options...) if err != nil { return nil, err } diff --git a/internal/pkg/test/containers/testcontainer/eventstoredb/eveentstoredb_container_test.go b/internal/pkg/test/containers/testcontainer/eventstoredb/eveentstoredb_container_test.go index 5a0438b0..b4c7ebbb 100644 --- a/internal/pkg/test/containers/testcontainer/eventstoredb/eveentstoredb_container_test.go +++ b/internal/pkg/test/containers/testcontainer/eventstoredb/eveentstoredb_container_test.go @@ -4,15 +4,30 @@ import ( "context" "testing" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/eventstroredb" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + "github.com/EventStore/EventStore-Client-Go/esdb" + "go.uber.org/fx" + "go.uber.org/fx/fxtest" ) func Test_Custom_EventStoreDB_Container(t *testing.T) { - esdbInstance, err := NewEventstoreDBTestContainers(defaultLogger.GetLogger()).Start(context.Background(), t) - require.NoError(t, err) + var esdbClient *esdb.Client + ctx := context.Background() - assert.NotNil(t, esdbInstance) + fxtest.New(t, + config.ModuleFunc(environment.Test), + zap.Module, + fxlog.FxLogger, + core.Module, + eventstroredb.ModuleFunc(func() { + }), + fx.Decorate(EventstoreDBContainerOptionsDecorator(t, ctx)), + fx.Populate(&esdbClient), + ).RequireStart() } diff --git a/internal/pkg/test/containers/testcontainer/eventstoredb/eventstoredb_container.go b/internal/pkg/test/containers/testcontainer/eventstoredb/eventstoredb_container.go index 6c71df30..0b7682a2 100644 --- a/internal/pkg/test/containers/testcontainer/eventstoredb/eventstoredb_container.go +++ b/internal/pkg/test/containers/testcontainer/eventstoredb/eventstoredb_container.go @@ -40,7 +40,7 @@ func NewEventstoreDBTestContainers(l logger.Logger) contracts.EventstoreDBContai } } -func (g *eventstoredbTestContainers) CreatingContainerOptions( +func (g *eventstoredbTestContainers) PopulateContainerOptions( ctx context.Context, t *testing.T, options ...*contracts.EventstoreDBContainerOptions, @@ -101,7 +101,7 @@ func (g *eventstoredbTestContainers) Start( t *testing.T, options ...*contracts.EventstoreDBContainerOptions, ) (*esdb.Client, error) { - eventstoredbOptions, err := g.CreatingContainerOptions(ctx, t, options...) + eventstoredbOptions, err := g.PopulateContainerOptions(ctx, t, options...) if err != nil { return nil, err } diff --git a/internal/pkg/test/containers/testcontainer/eventstoredb/eventstoredb_fx.go b/internal/pkg/test/containers/testcontainer/eventstoredb/eventstoredb_fx.go index 42a4ae09..7d08b66c 100644 --- a/internal/pkg/test/containers/testcontainer/eventstoredb/eventstoredb_fx.go +++ b/internal/pkg/test/containers/testcontainer/eventstoredb/eventstoredb_fx.go @@ -10,7 +10,7 @@ import ( var EventstoreDBContainerOptionsDecorator = func(t *testing.T, ctx context.Context) interface{} { return func(c *config.EventStoreDbOptions, logger logger.Logger) (*config.EventStoreDbOptions, error) { - newOption, err := NewEventstoreDBTestContainers(logger).CreatingContainerOptions(ctx, t) + newOption, err := NewEventstoreDBTestContainers(logger).PopulateContainerOptions(ctx, t) if err != nil { return nil, err } @@ -21,7 +21,7 @@ var EventstoreDBContainerOptionsDecorator = func(t *testing.T, ctx context.Conte } var ReplaceEventStoreContainerOptions = func(t *testing.T, options *config.EventStoreDbOptions, ctx context.Context, logger logger.Logger) error { - newOption, err := NewEventstoreDBTestContainers(logger).CreatingContainerOptions(ctx, t) + newOption, err := NewEventstoreDBTestContainers(logger).PopulateContainerOptions(ctx, t) if err != nil { return err } diff --git a/internal/pkg/test/containers/testcontainer/gorm/gorm_container.go b/internal/pkg/test/containers/testcontainer/gorm/gorm_container.go index 7b601369..36e21092 100644 --- a/internal/pkg/test/containers/testcontainer/gorm/gorm_container.go +++ b/internal/pkg/test/containers/testcontainer/gorm/gorm_container.go @@ -43,7 +43,7 @@ func NewGormTestContainers(l logger.Logger) contracts.GormContainer { } } -func (g *gormTestContainers) CreatingContainerOptions( +func (g *gormTestContainers) PopulateContainerOptions( ctx context.Context, t *testing.T, options ...*contracts.PostgresContainerOptions, @@ -85,7 +85,7 @@ func (g *gormTestContainers) CreatingContainerOptions( isConnectable := isConnectable(ctx, g.logger, g.defaultOptions) if !isConnectable { - return g.CreatingContainerOptions(context.Background(), t, options...) + return g.PopulateContainerOptions(context.Background(), t, options...) } g.container = dbContainer @@ -106,7 +106,7 @@ func (g *gormTestContainers) Start( t *testing.T, options ...*contracts.PostgresContainerOptions, ) (*gorm.DB, error) { - gormOptions, err := g.CreatingContainerOptions(ctx, t, options...) + gormOptions, err := g.PopulateContainerOptions(ctx, t, options...) if err != nil { return nil, err } diff --git a/internal/pkg/test/containers/testcontainer/gorm/gorm_container_test.go b/internal/pkg/test/containers/testcontainer/gorm/gorm_container_test.go index 9ed659dc..0e58867e 100644 --- a/internal/pkg/test/containers/testcontainer/gorm/gorm_container_test.go +++ b/internal/pkg/test/containers/testcontainer/gorm/gorm_container_test.go @@ -5,22 +5,37 @@ import ( "testing" "time" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" "github.com/docker/go-connections/nat" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/postgres" "github.com/testcontainers/testcontainers-go/wait" + "go.uber.org/fx" + "go.uber.org/fx/fxtest" + "gorm.io/gorm" ) func Test_Custom_Gorm_Container(t *testing.T) { ctx := context.Background() - gorm, err := NewGormTestContainers(defaultLogger.GetLogger()).Start(ctx, t) - require.NoError(t, err) + var gorm *gorm.DB + + fxtest.New(t, + config.ModuleFunc(environment.Test), + zap.Module, + fxlog.FxLogger, + core.Module, + gormPostgres.Module, + fx.Decorate(GormContainerOptionsDecorator(t, ctx)), + fx.Populate(&gorm), + ).RequireStart() assert.NotNil(t, gorm) } diff --git a/internal/pkg/test/containers/testcontainer/gorm/gorm_fx.go b/internal/pkg/test/containers/testcontainer/gorm/gorm_fx.go index 237f61fe..5b752225 100644 --- a/internal/pkg/test/containers/testcontainer/gorm/gorm_fx.go +++ b/internal/pkg/test/containers/testcontainer/gorm/gorm_fx.go @@ -10,6 +10,6 @@ import ( var GormContainerOptionsDecorator = func(t *testing.T, ctx context.Context) interface{} { return func(c *gormPostgres.GormOptions, logger logger.Logger) (*gormPostgres.GormOptions, error) { - return NewGormTestContainers(logger).CreatingContainerOptions(ctx, t) + return NewGormTestContainers(logger).PopulateContainerOptions(ctx, t) } } diff --git a/internal/pkg/test/containers/testcontainer/mongo/mongo_container.go b/internal/pkg/test/containers/testcontainer/mongo/mongo_container.go index 7ed4d962..9dc18477 100644 --- a/internal/pkg/test/containers/testcontainer/mongo/mongo_container.go +++ b/internal/pkg/test/containers/testcontainer/mongo/mongo_container.go @@ -48,7 +48,7 @@ func NewMongoTestContainers(l logger.Logger) contracts.MongoContainer { } } -func (g *mongoTestContainers) CreatingContainerOptions( +func (g *mongoTestContainers) PopulateContainerOptions( ctx context.Context, t *testing.T, options ...*contracts.MongoContainerOptions, @@ -76,7 +76,10 @@ func (g *mongoTestContainers) CreatingContainerOptions( }) // get a free random host hostPort - hostPort, err := dbContainer.MappedPort(ctx, nat.Port(g.defaultOptions.Port)) + hostPort, err := dbContainer.MappedPort( + ctx, + nat.Port(g.defaultOptions.Port), + ) if err != nil { return nil, err } @@ -89,7 +92,7 @@ func (g *mongoTestContainers) CreatingContainerOptions( isConnectable := isConnectable(ctx, g.logger, g.defaultOptions) if !isConnectable { - return g.CreatingContainerOptions(context.Background(), t, options...) + return g.PopulateContainerOptions(context.Background(), t, options...) } g.container = dbContainer @@ -106,24 +109,6 @@ func (g *mongoTestContainers) CreatingContainerOptions( return option, nil } -func (g *mongoTestContainers) Start( - ctx context.Context, - t *testing.T, - options ...*contracts.MongoContainerOptions, -) (*mongo.Client, error) { - mongoOptions, err := g.CreatingContainerOptions(ctx, t, options...) - if err != nil { - return nil, err - } - - db, err := mongodb.NewMongoDB(mongoOptions) - if err != nil { - return nil, err - } - - return db, nil -} - func (g *mongoTestContainers) Cleanup(ctx context.Context) error { if err := g.container.Terminate(ctx); err != nil { return errors.WrapIf(err, "failed to terminate container: %s") @@ -158,10 +143,15 @@ func (g *mongoTestContainers) getRunOptions( } containerReq := testcontainers.ContainerRequest{ - Image: fmt.Sprintf("%s:%s", g.defaultOptions.ImageName, g.defaultOptions.Tag), + Image: fmt.Sprintf( + "%s:%s", + g.defaultOptions.ImageName, + g.defaultOptions.Tag, + ), ExposedPorts: []string{g.defaultOptions.Port}, - WaitingFor: wait.ForListeningPort(nat.Port(g.defaultOptions.Port)).WithPollInterval(2 * time.Second), - Hostname: g.defaultOptions.Host, + WaitingFor: wait.ForListeningPort(nat.Port(g.defaultOptions.Port)). + WithPollInterval(2 * time.Second), + Hostname: g.defaultOptions.Host, HostConfigModifier: func(hostConfig *container.HostConfig) { hostConfig.AutoRemove = true }, @@ -174,7 +164,11 @@ func (g *mongoTestContainers) getRunOptions( return containerReq } -func isConnectable(ctx context.Context, logger logger.Logger, mongoOptions *contracts.MongoContainerOptions) bool { +func isConnectable( + ctx context.Context, + logger logger.Logger, + mongoOptions *contracts.MongoContainerOptions, +) bool { uriAddress := fmt.Sprintf( "mongodb://%s:%s@%s:%d", mongoOptions.UserName, @@ -187,7 +181,12 @@ func isConnectable(ctx context.Context, logger logger.Logger, mongoOptions *cont SetMaxConnIdleTime(maxConnIdleTime). SetMinPoolSize(minPoolSize). SetMaxPoolSize(maxPoolSize) - opt = opt.SetAuth(options.Credential{Username: mongoOptions.UserName, Password: mongoOptions.Password}) + opt = opt.SetAuth( + options.Credential{ + Username: mongoOptions.UserName, + Password: mongoOptions.Password, + }, + ) mongoClient, err := mongo.Connect(ctx, opt) @@ -206,7 +205,10 @@ func isConnectable(ctx context.Context, logger logger.Logger, mongoOptions *cont return false } logger.Infof( - "Opened mongodb connection on host: %s:%d", mongoOptions.Host, mongoOptions.HostPort) + "Opened mongodb connection on host: %s:%d", + mongoOptions.Host, + mongoOptions.HostPort, + ) return true } diff --git a/internal/pkg/test/containers/testcontainer/mongo/mongo_container_test.go b/internal/pkg/test/containers/testcontainer/mongo/mongo_container_test.go index fb0c8b8f..61141b13 100644 --- a/internal/pkg/test/containers/testcontainer/mongo/mongo_container_test.go +++ b/internal/pkg/test/containers/testcontainer/mongo/mongo_container_test.go @@ -4,17 +4,33 @@ import ( "context" "testing" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + "go.mongodb.org/mongo-driver/mongo" + "go.uber.org/fx" + "go.uber.org/fx/fxtest" ) func Test_Custom_Mongo_Container(t *testing.T) { - mongo, err := NewMongoTestContainers( - defaultLogger.GetLogger(), - ).Start(context.Background(), t) - require.NoError(t, err) + ctx := context.Background() - assert.NotNil(t, mongo) + var mongoClient *mongo.Client + + fxtest.New(t, + config.ModuleFunc(environment.Test), + zap.Module, + fxlog.FxLogger, + core.Module, + mongodb.Module, + fx.Decorate(MongoContainerOptionsDecorator(t, ctx)), + fx.Populate(&mongoClient), + ).RequireStart() + + assert.NotNil(t, mongoClient) } diff --git a/internal/pkg/test/containers/testcontainer/mongo/mongo_fx.go b/internal/pkg/test/containers/testcontainer/mongo/mongo_fx.go index f9ed16a6..daa323b2 100644 --- a/internal/pkg/test/containers/testcontainer/mongo/mongo_fx.go +++ b/internal/pkg/test/containers/testcontainer/mongo/mongo_fx.go @@ -10,6 +10,6 @@ import ( var MongoContainerOptionsDecorator = func(t *testing.T, ctx context.Context) interface{} { return func(c *mongodb.MongoDbOptions, logger logger.Logger) (*mongodb.MongoDbOptions, error) { - return NewMongoTestContainers(logger).CreatingContainerOptions(ctx, t) + return NewMongoTestContainers(logger).PopulateContainerOptions(ctx, t) } } diff --git a/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_container.go b/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_container.go index 2fa22079..a051afba 100644 --- a/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_container.go +++ b/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_container.go @@ -40,7 +40,7 @@ func NewPostgresPgxContainers(l logger.Logger) contracts.PostgresPgxContainer { } } -func (g *postgresPgxTestContainers) CreatingContainerOptions( +func (g *postgresPgxTestContainers) PopulateContainerOptions( ctx context.Context, t *testing.T, options ...*contracts.PostgresContainerOptions, @@ -97,7 +97,7 @@ func (g *postgresPgxTestContainers) Start( t *testing.T, options ...*contracts.PostgresContainerOptions, ) (*postgres.Pgx, error) { - postgresPgxOptions, err := g.CreatingContainerOptions(ctx, t, options...) + postgresPgxOptions, err := g.PopulateContainerOptions(ctx, t, options...) if err != nil { return nil, err } diff --git a/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_fx.go b/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_fx.go index 9ad471e8..889e1f4e 100644 --- a/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_fx.go +++ b/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_fx.go @@ -10,6 +10,6 @@ import ( var PostgresPgxContainerOptionsDecorator = func(t *testing.T, ctx context.Context) interface{} { return func(c *postgres.PostgresPgxOptions, logger logger.Logger) (*postgres.PostgresPgxOptions, error) { - return NewPostgresPgxContainers(logger).CreatingContainerOptions(ctx, t) + return NewPostgresPgxContainers(logger).PopulateContainerOptions(ctx, t) } } diff --git a/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_container.go b/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_container.go index 9c3af822..c5edf961 100644 --- a/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_container.go +++ b/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_container.go @@ -6,13 +6,8 @@ import ( "testing" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/bus" - bus2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/bus" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/contracts" "emperror.dev/errors" @@ -51,7 +46,7 @@ func NewRabbitMQTestContainers(l logger.Logger) contracts.RabbitMQContainer { } } -func (g *rabbitmqTestContainers) CreatingContainerOptions( +func (g *rabbitmqTestContainers) PopulateContainerOptions( ctx context.Context, t *testing.T, options ...*contracts.RabbitMQContainerOptions, @@ -60,7 +55,6 @@ func (g *rabbitmqTestContainers) CreatingContainerOptions( // https://dev.to/remast/go-integration-tests-using-testcontainers-9o5 containerReq := g.getRunOptions(options...) - // TODO: Using Parallel Container dbContainer, err := testcontainers.GenericContainer( ctx, testcontainers.GenericContainerRequest{ @@ -109,7 +103,7 @@ func (g *rabbitmqTestContainers) CreatingContainerOptions( isConnectable := IsConnectable(g.logger, g.defaultOptions) if !isConnectable { - return g.CreatingContainerOptions(context.Background(), t, options...) + return g.PopulateContainerOptions(context.Background(), t, options...) } g.container = dbContainer @@ -126,45 +120,6 @@ func (g *rabbitmqTestContainers) CreatingContainerOptions( return option, nil } -func (g *rabbitmqTestContainers) Start( - ctx context.Context, - t *testing.T, - serializer serializer.EventSerializer, - rabbitmqBuilderFunc configurations.RabbitMQConfigurationBuilderFuc, - options ...*contracts.RabbitMQContainerOptions, -) (bus.Bus, error) { - rabbitHostOptions, err := g.CreatingContainerOptions(ctx, t, options...) - if err != nil { - return nil, err - } - - g.logger.Infof( - "rabbitmq connection is on host: %s", - rabbitHostOptions.AmqpEndPoint(), - ) - - rabbitmqConfig := &config.RabbitmqOptions{ - RabbitmqHostOptions: rabbitHostOptions, - } - conn, err := types.NewRabbitMQConnection(rabbitmqConfig) - if err != nil { - return nil, err - } - - mqBus, err := bus2.NewRabbitmqBus( - rabbitmqConfig, - serializer, - g.logger, - conn, - rabbitmqBuilderFunc, - ) - if err != nil { - return nil, err - } - - return mqBus, nil -} - func (g *rabbitmqTestContainers) Cleanup(ctx context.Context) error { if err := g.container.Terminate(ctx); err != nil { return errors.WrapIf(err, "failed to terminate container: %s") @@ -258,6 +213,7 @@ func IsConnectable( options.Password, ) _, err = rmqc.ListExchanges() + if err != nil { logger.Errorf( "Error in creating rabbitmq connection with http host: %s", diff --git a/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_container_test.go b/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_container_test.go index db6716ef..910c366d 100644 --- a/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_container_test.go +++ b/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_container_test.go @@ -5,11 +5,17 @@ import ( "testing" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/json" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/bus" messageConsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + rabbitmq2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" rabbitmqConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" consumerConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging/consumer" @@ -17,36 +23,50 @@ import ( uuid "github.com/satori/go.uuid" "github.com/stretchr/testify/require" + "go.uber.org/fx" + "go.uber.org/fx/fxtest" ) func Test_Custom_RabbitMQ_Container(t *testing.T) { ctx := context.Background() fakeConsumer := consumer.NewRabbitMQFakeTestConsumerHandler[*ProducerConsumerMessage]() - eventSerializer := serializer.NewDefaultEventSerializer(json.NewDefaultSerializer()) - rabbitmq, err := NewRabbitMQTestContainers( - defaultLogger.GetLogger(), - ).Start(ctx, t, eventSerializer, func(builder rabbitmqConfigurations.RabbitMQConfigurationBuilder) { - builder.AddConsumer(ProducerConsumerMessage{}, - func(consumerBuilder consumerConfigurations.RabbitMQConsumerConfigurationBuilder) { - consumerBuilder.WithHandlers( - func(handlerBuilder messageConsumer.ConsumerHandlerConfigurationBuilder) { - handlerBuilder.AddHandler(fakeConsumer) - }, - ) - }) - }) + var rabbitmqbus bus.Bus - require.NoError(t, err) - require.NotNil(t, rabbitmq) + fxtest.New(t, + config.ModuleFunc(environment.Test), + zap.Module, + fxlog.FxLogger, + core.Module, + rabbitmq2.ModuleFunc( + func(l logger.Logger) rabbitmqConfigurations.RabbitMQConfigurationBuilderFuc { + return func(builder configurations.RabbitMQConfigurationBuilder) { + builder.AddConsumer( + ProducerConsumerMessage{}, + func(consumerBuilder consumerConfigurations.RabbitMQConsumerConfigurationBuilder) { + consumerBuilder.WithHandlers( + func(handlerBuilder messageConsumer.ConsumerHandlerConfigurationBuilder) { + handlerBuilder.AddHandler(fakeConsumer) + }, + ) + }, + ) + } + }, + ), + fx.Decorate(RabbitmqContainerOptionsDecorator(t, ctx)), + fx.Populate(&rabbitmqbus), + ).RequireStart() + + require.NotNil(t, rabbitmqbus) - err = rabbitmq.Start(ctx) + err := rabbitmqbus.Start(ctx) require.NoError(t, err) - // wait for consumers ready to consume before publishing messages (for preventing messages lost) + //// wait for consumers ready to consume before publishing messages (for preventing messages lost) time.Sleep(time.Second * 1) - err = rabbitmq.PublishMessage( + err = rabbitmqbus.PublishMessage( context.Background(), &ProducerConsumerMessage{ Data: "ssssssssss", diff --git a/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_fx.go b/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_fx.go index 3dcc0e5d..4dd0a4e2 100644 --- a/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_fx.go +++ b/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_fx.go @@ -10,7 +10,7 @@ import ( var RabbitmqContainerOptionsDecorator = func(t *testing.T, ctx context.Context) interface{} { return func(c *config.RabbitmqOptions, logger logger.Logger) (*config.RabbitmqOptions, error) { - rabbitmqHostOptions, err := NewRabbitMQTestContainers(logger).CreatingContainerOptions(ctx, t) + rabbitmqHostOptions, err := NewRabbitMQTestContainers(logger).PopulateContainerOptions(ctx, t) c.RabbitmqHostOptions = rabbitmqHostOptions return c, err diff --git a/internal/pkg/test/containers/testcontainer/redis/redis_container.go b/internal/pkg/test/containers/testcontainer/redis/redis_container.go index c2dcb052..f45526aa 100644 --- a/internal/pkg/test/containers/testcontainer/redis/redis_container.go +++ b/internal/pkg/test/containers/testcontainer/redis/redis_container.go @@ -38,7 +38,7 @@ func NewRedisTestContainers(l logger.Logger) contracts.RedisContainer { } } -func (g *redisTestContainers) CreatingContainerOptions( +func (g *redisTestContainers) PopulateContainerOptions( ctx context.Context, t *testing.T, options ...*contracts.RedisContainerOptions, @@ -66,7 +66,10 @@ func (g *redisTestContainers) CreatingContainerOptions( }) // get a free random host hostPort - hostPort, err := dbContainer.MappedPort(ctx, nat.Port(g.defaultOptions.Port)) + hostPort, err := dbContainer.MappedPort( + ctx, + nat.Port(g.defaultOptions.Port), + ) if err != nil { return nil, err } @@ -79,7 +82,7 @@ func (g *redisTestContainers) CreatingContainerOptions( isConnectable := isConnectable(ctx, g.logger, g.defaultOptions) if !isConnectable { - return g.CreatingContainerOptions(context.Background(), t, options...) + return g.PopulateContainerOptions(context.Background(), t, options...) } g.container = dbContainer @@ -93,21 +96,6 @@ func (g *redisTestContainers) CreatingContainerOptions( return reidsOptions, nil } -func (g *redisTestContainers) Start( - ctx context.Context, - t *testing.T, - options ...*contracts.RedisContainerOptions, -) (redis.UniversalClient, error) { - redisOptions, err := g.CreatingContainerOptions(ctx, t, options...) - - db := redis2.NewRedisClient(redisOptions) - if err != nil { - return nil, err - } - - return db, nil -} - func (g *redisTestContainers) Cleanup(ctx context.Context) error { if err := g.container.Terminate(ctx); err != nil { return errors.WrapIf(err, "failed to terminate container: %s") @@ -136,7 +124,11 @@ func (g *redisTestContainers) getRunOptions( } containerReq := testcontainers.ContainerRequest{ - Image: fmt.Sprintf("%s:%s", g.defaultOptions.ImageName, g.defaultOptions.Tag), + Image: fmt.Sprintf( + "%s:%s", + g.defaultOptions.ImageName, + g.defaultOptions.Tag, + ), ExposedPorts: []string{g.defaultOptions.Port}, WaitingFor: wait.ForListeningPort(nat.Port(g.defaultOptions.Port)). WithPollInterval(2 * time.Second), @@ -147,7 +139,11 @@ func (g *redisTestContainers) getRunOptions( return containerReq } -func isConnectable(ctx context.Context, logger logger.Logger, options *contracts.RedisContainerOptions) bool { +func isConnectable( + ctx context.Context, + logger logger.Logger, + options *contracts.RedisContainerOptions, +) bool { redisClient := redis.NewClient(&redis.Options{ Addr: fmt.Sprintf("%s:%d", options.Host, options.HostPort), }) @@ -158,13 +154,18 @@ func isConnectable(ctx context.Context, logger logger.Logger, options *contracts if err != nil { // we should not use `t.Error` or `t.Errorf` for logging errors because it will `fail` our test at the end and, we just should use logs without error like log.Error (not log.Fatal) logger.Errorf( - "Error in creating redis connection with %s:%d", options.Host, options.HostPort) + "Error in creating redis connection with %s:%d", + options.Host, + options.HostPort, + ) return false } logger.Infof( - "Opened redis connection on host: %s:%d", options.Host, options.HostPort, + "Opened redis connection on host: %s:%d", + options.Host, + options.HostPort, ) return true diff --git a/internal/pkg/test/containers/testcontainer/redis/redis_container_test.go b/internal/pkg/test/containers/testcontainer/redis/redis_container_test.go index fd05ece6..3f5dd7af 100644 --- a/internal/pkg/test/containers/testcontainer/redis/redis_container_test.go +++ b/internal/pkg/test/containers/testcontainer/redis/redis_container_test.go @@ -4,15 +4,32 @@ import ( "context" "testing" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" + redis2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/redis" + "github.com/redis/go-redis/v9" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + "go.uber.org/fx" + "go.uber.org/fx/fxtest" ) func Test_Custom_Redis_Container(t *testing.T) { - redis, err := NewRedisTestContainers(defaultLogger.GetLogger()).Start(context.Background(), t) - require.NoError(t, err) + ctx := context.Background() + var redisClient redis.UniversalClient - assert.NotNil(t, redis) + fxtest.New(t, + config.ModuleFunc(environment.Test), + zap.Module, + fxlog.FxLogger, + core.Module, + redis2.Module, + fx.Decorate(RedisContainerOptionsDecorator(t, ctx)), + fx.Populate(&redisClient), + ).RequireStart() + + assert.NotNil(t, redisClient) } diff --git a/internal/pkg/test/containers/testcontainer/redis/redis_fx.go b/internal/pkg/test/containers/testcontainer/redis/redis_fx.go index 418274a1..88cd70cf 100644 --- a/internal/pkg/test/containers/testcontainer/redis/redis_fx.go +++ b/internal/pkg/test/containers/testcontainer/redis/redis_fx.go @@ -10,6 +10,6 @@ import ( var RedisContainerOptionsDecorator = func(t *testing.T, ctx context.Context) interface{} { return func(c *redis.RedisOptions, logger logger.Logger) (*redis.RedisOptions, error) { - return NewRedisTestContainers(logger).CreatingContainerOptions(ctx, t) + return NewRedisTestContainers(logger).PopulateContainerOptions(ctx, t) } } diff --git a/internal/pkg/validation/validation.go b/internal/pkg/validation/validation.go new file mode 100644 index 00000000..bcf5f758 --- /dev/null +++ b/internal/pkg/validation/validation.go @@ -0,0 +1,5 @@ +package validation + +type Validator interface { + Validate() error +} diff --git a/internal/services/catalog_read_service/config/config.development.json b/internal/services/catalog_read_service/config/config.development.json index 05a58d3b..b8f8f6fc 100644 --- a/internal/services/catalog_read_service/config/config.development.json +++ b/internal/services/catalog_read_service/config/config.development.json @@ -108,8 +108,5 @@ }, "elasticIndexes": { "products": "products" - }, - "eventStoreDbOptions": { - "connectionString": "esdb://localhost:2113?tls=false" } } diff --git a/internal/services/catalog_read_service/config/config.go b/internal/services/catalog_read_service/config/config.go index 6ea4dc98..0ee2cccf 100644 --- a/internal/services/catalog_read_service/config/config.go +++ b/internal/services/catalog_read_service/config/config.go @@ -4,14 +4,14 @@ import ( "strings" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" ) type Config struct { AppOptions AppOptions `mapstructure:"appOptions" env:"AppOptions"` } -func NewConfig(env environemnt.Environment) (*Config, error) { +func NewConfig(env environment.Environment) (*Config, error) { cfg, err := config.BindConfig[*Config](env) if err != nil { return nil, err diff --git a/internal/services/catalog_read_service/config/config.test.json b/internal/services/catalog_read_service/config/config.test.json index a0d095ac..0fa84110 100644 --- a/internal/services/catalog_read_service/config/config.test.json +++ b/internal/services/catalog_read_service/config/config.test.json @@ -102,8 +102,5 @@ }, "elasticIndexes": { "products": "products" - }, - "eventStoreDbOptions": { - "connectionString": "esdb://localhost:2113?tls=false" } } diff --git a/internal/services/catalog_read_service/go.mod b/internal/services/catalog_read_service/go.mod index bed94a78..989903f6 100644 --- a/internal/services/catalog_read_service/go.mod +++ b/internal/services/catalog_read_service/go.mod @@ -13,7 +13,7 @@ require ( github.com/go-playground/validator v9.31.0+incompatible github.com/labstack/echo/v4 v4.11.1 github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg v0.0.0-20230831075934-be8df319f588 - github.com/mehdihadeli/go-mediatr v1.2.0 + github.com/mehdihadeli/go-mediatr v1.3.0 github.com/michaelklishin/rabbit-hole v1.5.0 github.com/pterm/pterm v0.12.69 github.com/redis/go-redis/v9 v9.2.1 diff --git a/internal/services/catalog_read_service/go.sum b/internal/services/catalog_read_service/go.sum index 4049ad4d..024e0f77 100644 --- a/internal/services/catalog_read_service/go.sum +++ b/internal/services/catalog_read_service/go.sum @@ -522,6 +522,8 @@ github.com/mehdihadeli/go-mediatr v1.1.10 h1:NAzg4065c90lgYeb+Vzbd2WKH0tUFpxzL0m github.com/mehdihadeli/go-mediatr v1.1.10/go.mod h1:lwgZl7qVL/RKomObBblhG3uEte/r4nJDV95Vd+nGrMw= github.com/mehdihadeli/go-mediatr v1.2.0 h1:XkzYF/uGfW4pwPWYAxKyY+mO6l989PbmCQWSYHuCZtU= github.com/mehdihadeli/go-mediatr v1.2.0/go.mod h1:I9LuExxAKz6cTDJyP/SSDSmkHaPHK1/usnvEXjUY47k= +github.com/mehdihadeli/go-mediatr v1.3.0 h1:hrb5Scp/nsiR3Y62mjZ0Tc5UX/dRJl4nDFkINBEIESA= +github.com/mehdihadeli/go-mediatr v1.3.0/go.mod h1:lsG+hyH+pEOhmZiZl0KPO72BcZiEReF03CBk4GVJB0k= github.com/michaelklishin/rabbit-hole v1.5.0 h1:Bex27BiFDsijCM9D0ezSHqyy0kehpYHuNKaPqq/a4RM= github.com/michaelklishin/rabbit-hole v1.5.0/go.mod h1:vvI1uOitYZi0O5HEGXhaWC1XT80Gy+HvFheJ+5Krlhk= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= diff --git a/internal/services/catalog_read_service/internal/products/configurations/mediator/mediator_configurations.go b/internal/services/catalog_read_service/internal/products/configurations/mediator/mediator_configurations.go index 7f929af7..da5b63ed 100644 --- a/internal/services/catalog_read_service/internal/products/configurations/mediator/mediator_configurations.go +++ b/internal/services/catalog_read_service/internal/products/configurations/mediator/mediator_configurations.go @@ -4,7 +4,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" - createProductCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/commands" + v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1" createProductDtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/dtos" deleteProductCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/deleting_products/v1/commands" getProductByIdDtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/dtos" @@ -25,8 +25,8 @@ func ConfigProductsMediator( cacheProductRepository data.ProductCacheRepository, tracer tracing.AppTracer, ) error { - err := mediatr.RegisterRequestHandler[*createProductCommandV1.CreateProduct, *createProductDtosV1.CreateProductResponseDto]( - createProductCommandV1.NewCreateProductHandler( + err := mediatr.RegisterRequestHandler[*v1.CreateProduct, *createProductDtosV1.CreateProductResponseDto]( + v1.NewCreateProductHandler( logger, mongoProductRepository, cacheProductRepository, diff --git a/internal/services/catalog_read_service/internal/products/configurations/products_module_configurator.go b/internal/services/catalog_read_service/internal/products/configurations/products_module_configurator.go index d32d6c13..1398c3bd 100644 --- a/internal/services/catalog_read_service/internal/products/configurations/products_module_configurator.go +++ b/internal/services/catalog_read_service/internal/products/configurations/products_module_configurator.go @@ -1,10 +1,10 @@ package configurations import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" logger2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/configurations/mappings" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/configurations/mediator" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" @@ -26,7 +26,12 @@ func (c *ProductsModuleConfigurator) ConfigureProductsModule() { c.ResolveFunc( func(logger logger2.Logger, mongoRepository data.ProductRepository, cacheRepository data.ProductCacheRepository, tracer tracing.AppTracer) error { // config Products Mediators - err := mediator.ConfigProductsMediator(logger, mongoRepository, cacheRepository, tracer) + err := mediator.ConfigProductsMediator( + logger, + mongoRepository, + cacheRepository, + tracer, + ) if err != nil { return err } diff --git a/internal/services/catalog_read_service/internal/products/configurations/rabbitmq/rabbitmq_configuration.go b/internal/services/catalog_read_service/internal/products/configurations/rabbitmq/rabbitmq_configuration.go index d86e8907..1d7a1de9 100644 --- a/internal/services/catalog_read_service/internal/products/configurations/rabbitmq/rabbitmq_configuration.go +++ b/internal/services/catalog_read_service/internal/products/configurations/rabbitmq/rabbitmq_configuration.go @@ -6,7 +6,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" rabbitmqConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" - createProductExternalEventV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/events/integration_events/external_events" + createProductExternalEventV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/events/integrationevents/externalevents" deleteProductExternalEventV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/deleting_products/v1/events/integration_events/external_events" updateProductExternalEventsV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/updating_products/v1/events/integration_events/external_events" diff --git a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/commands/create_product.go b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/create_product.go similarity index 98% rename from internal/services/catalog_read_service/internal/products/features/creating_product/v1/commands/create_product.go rename to internal/services/catalog_read_service/internal/products/features/creating_product/v1/create_product.go index 16671916..2fb186d0 100644 --- a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/commands/create_product.go +++ b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/create_product.go @@ -1,4 +1,4 @@ -package commands +package v1 import ( "time" diff --git a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/commands/create_product_handler.go b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/create_product_handler.go similarity index 99% rename from internal/services/catalog_read_service/internal/products/features/creating_product/v1/commands/create_product_handler.go rename to internal/services/catalog_read_service/internal/products/features/creating_product/v1/create_product_handler.go index b6c1d1ed..b8eb7309 100644 --- a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/commands/create_product_handler.go +++ b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/create_product_handler.go @@ -1,4 +1,4 @@ -package commands +package v1 import ( "context" diff --git a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integration_events/external_events/product_created.go b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integration_events/external_events/product_created.go rename to internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created.go diff --git a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integration_events/external_events/product_created_consumer.go b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created_consumer.go similarity index 87% rename from internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integration_events/external_events/product_created_consumer.go rename to internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created_consumer.go index 1c4e3582..dc9030f6 100644 --- a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integration_events/external_events/product_created_consumer.go +++ b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created_consumer.go @@ -9,7 +9,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/commands" + v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/dtos" "emperror.dev/errors" @@ -44,7 +44,7 @@ func (c *productCreatedConsumer) Handle( return errors.New("error in casting message to ProductCreatedV1") } - command, err := commands.NewCreateProduct( + command, err := v1.NewCreateProduct( product.ProductId, product.Name, product.Description, @@ -59,7 +59,7 @@ func (c *productCreatedConsumer) Handle( return validationErr } - _, err = mediatr.Send[*commands.CreateProduct, *dtos.CreateProductResponseDto]( + _, err = mediatr.Send[*v1.CreateProduct, *dtos.CreateProductResponseDto]( ctx, command, ) diff --git a/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/endpoints/get_product_by_id_endpoint.go b/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/endpoints/get_product_by_id_endpoint.go index cd78bb03..da5a4c16 100644 --- a/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/endpoints/get_product_by_id_endpoint.go +++ b/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/endpoints/get_product_by_id_endpoint.go @@ -3,8 +3,8 @@ package endpoints import ( "net/http" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/params" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/queries" diff --git a/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/queries/get_product_by_id_handler.go b/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/queries/get_product_by_id_handler.go index 291a4a08..58b4b2ff 100644 --- a/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/queries/get_product_by_id_handler.go +++ b/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/queries/get_product_by_id_handler.go @@ -8,14 +8,10 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/dto" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/models" - - attribute2 "go.opentelemetry.io/otel/attribute" ) type GetProductByIdHandler struct { @@ -43,36 +39,29 @@ func (q *GetProductByIdHandler) Handle( ctx context.Context, query *GetProductById, ) (*dtos.GetProductByIdResponseDto, error) { - ctx, span := q.tracer.Start(ctx, "getProductByIdHandler.Handle") - span.SetAttributes(attribute.Object("Query", query)) - span.SetAttributes(attribute2.String("Id", query.Id.String())) - - redisProduct, err := q.redisRepository.GetProductById(ctx, query.Id.String()) - - var product *models.Product - - defer span.End() - + redisProduct, err := q.redisRepository.GetProductById( + ctx, + query.Id.String(), + ) if err != nil { - return nil, utils.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - fmt.Sprintf( - "[GetProductByIdHandler_Handle.GetProductById] error in getting product with id %d in the redis repository", - query.Id, - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + fmt.Sprintf( + "error in getting product with id %d in the redis repository", + query.Id, ), ) } + var product *models.Product + if redisProduct != nil { product = redisProduct } else { var mongoProduct *models.Product mongoProduct, err = q.mongoRepository.GetProductById(ctx, query.Id.String()) if err != nil { - return nil, utils.TraceErrFromSpan(span, customErrors.NewApplicationErrorWrap(err, fmt.Sprintf("[GetProductByIdHandler_Handle.GetProductById] error in getting product with id %d in the mongo repository", query.Id))) + return nil, customErrors.NewApplicationErrorWrap(err, fmt.Sprintf("error in getting product with id %d in the mongo repository", query.Id)) } if mongoProduct == nil { mongoProduct, err = q.mongoRepository.GetProductByProductId(ctx, query.Id.String()) @@ -84,23 +73,23 @@ func (q *GetProductByIdHandler) Handle( product = mongoProduct err = q.redisRepository.PutProduct(ctx, product.Id, product) if err != nil { - return new(dtos.GetProductByIdResponseDto), utils.TraceErrFromSpan(span, err) + return new(dtos.GetProductByIdResponseDto), err } } productDto, err := mapper.Map[*dto.ProductDto](product) if err != nil { - return nil, utils.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[GetProductByIdHandler_Handle.Map] error in the mapping product", - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in the mapping product", ) } q.log.Infow( - fmt.Sprintf("[GetProductByIdHandler.Handle] product with id: {%s} fetched", query.Id), + fmt.Sprintf( + "product with id: {%s} fetched", + query.Id, + ), logger.Fields{"ProductId": product.ProductId, "Id": product.Id}, ) diff --git a/internal/services/catalog_read_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go b/internal/services/catalog_read_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go index 2179f01e..1ecf134c 100644 --- a/internal/services/catalog_read_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go +++ b/internal/services/catalog_read_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go @@ -1,12 +1,11 @@ package endpoints import ( - "fmt" "net/http" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/params" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/getting_products/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/getting_products/v1/queries" @@ -44,32 +43,24 @@ func (ep *getProductsEndpoint) MapEndpoint() { func (ep *getProductsEndpoint) handler() echo.HandlerFunc { return func(c echo.Context) error { ctx := c.Request().Context() - ep.CatalogsMetrics.GetProductsHttpRequests.Add(ctx, 1) listQuery, err := utils.GetListQueryFromCtx(c) if err != nil { badRequestErr := customErrors.NewBadRequestErrorWrap( err, - "[getProductsEndpoint_handler.GetListQueryFromCtx] error in getting data from query string", + "error in getting data from query string", ) - ep.Logger.Errorf( - fmt.Sprintf( - "[getProductsEndpoint_handler.GetListQueryFromCtx] err: %v", - badRequestErr, - ), - ) - return err + + return badRequestErr } request := queries.NewGetProducts(listQuery) if err := c.Bind(request); err != nil { badRequestErr := customErrors.NewBadRequestErrorWrap( err, - "[getProductsEndpoint_handler.Bind] error in the binding request", - ) - ep.Logger.Errorf( - fmt.Sprintf("[getProductsEndpoint_handler.Bind] err: %v", badRequestErr), + "error in the binding request", ) + return badRequestErr } query := &queries.GetProducts{ListQuery: request.ListQuery} @@ -79,12 +70,10 @@ func (ep *getProductsEndpoint) handler() echo.HandlerFunc { query, ) if err != nil { - err = errors.WithMessage( + return errors.WithMessage( err, - "[getProductsEndpoint_handler.Send] error in sending GetProducts", + "error in sending GetProducts", ) - ep.Logger.Error(fmt.Sprintf("[getProductsEndpoint_handler.Send] err: {%v}", err)) - return err } return c.JSON(http.StatusOK, queryResult) diff --git a/internal/services/catalog_read_service/internal/products/features/getting_products/v1/queries/get_products_handler.go b/internal/services/catalog_read_service/internal/products/features/getting_products/v1/queries/get_products_handler.go index 12894870..1cba0c1c 100644 --- a/internal/services/catalog_read_service/internal/products/features/getting_products/v1/queries/get_products_handler.go +++ b/internal/services/catalog_read_service/internal/products/features/getting_products/v1/queries/get_products_handler.go @@ -6,8 +6,6 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" - utils2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/dto" @@ -25,40 +23,36 @@ func NewGetProductsHandler( mongoRepository data.ProductRepository, tracer tracing.AppTracer, ) *GetProductsHandler { - return &GetProductsHandler{log: log, mongoRepository: mongoRepository, tracer: tracer} + return &GetProductsHandler{ + log: log, + mongoRepository: mongoRepository, + tracer: tracer, + } } func (c *GetProductsHandler) Handle( ctx context.Context, query *GetProducts, ) (*dtos.GetProductsResponseDto, error) { - ctx, span := c.tracer.Start(ctx, "GetProductsHandler.Handle") - span.SetAttributes(attribute.Object("Query", query)) - defer span.End() - products, err := c.mongoRepository.GetAllProducts(ctx, query.ListQuery) if err != nil { - return nil, utils2.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[GetProductsHandler_Handle.GetAllProducts] error in getting products in the repository", - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in getting products in the repository", ) } - listResultDto, err := utils.ListResultToListResultDto[*dto.ProductDto](products) + listResultDto, err := utils.ListResultToListResultDto[*dto.ProductDto]( + products, + ) if err != nil { - return nil, utils2.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[GetProductsHandler_Handle.ListResultToListResultDto] error in the mapping ListResultToListResultDto", - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in the mapping ListResultToListResultDto", ) } - c.log.Info("[GetProductsHandler.Handle] products fetched") + c.log.Info("products fetched") return &dtos.GetProductsResponseDto{Products: listResultDto}, nil } diff --git a/internal/services/catalog_read_service/internal/products/features/searching_products/v1/endpoints/search_products_endpoint.go b/internal/services/catalog_read_service/internal/products/features/searching_products/v1/endpoints/search_products_endpoint.go index 36892c0a..e33447c3 100644 --- a/internal/services/catalog_read_service/internal/products/features/searching_products/v1/endpoints/search_products_endpoint.go +++ b/internal/services/catalog_read_service/internal/products/features/searching_products/v1/endpoints/search_products_endpoint.go @@ -1,12 +1,11 @@ package endpoints import ( - "fmt" "net/http" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/params" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/searching_products/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/searching_products/v1/queries" @@ -44,21 +43,15 @@ func (ep *searchProductsEndpoint) MapEndpoint() { func (ep *searchProductsEndpoint) handler() echo.HandlerFunc { return func(c echo.Context) error { ctx := c.Request().Context() - ep.CatalogsMetrics.SearchProductHttpRequests.Add(ctx, 1) listQuery, err := utils.GetListQueryFromCtx(c) if err != nil { badRequestErr := customErrors.NewBadRequestErrorWrap( err, - "[searchProductsEndpoint_handler.GetListQueryFromCtx] error in getting data from query string", + "error in getting data from query string", ) - ep.Logger.Errorf( - fmt.Sprintf( - "[searchProductsEndpoint_handler.GetListQueryFromCtx] err: %v", - badRequestErr, - ), - ) - return err + + return badRequestErr } request := &dtos.SearchProductsRequestDto{ListQuery: listQuery} @@ -66,11 +59,9 @@ func (ep *searchProductsEndpoint) handler() echo.HandlerFunc { if err := c.Bind(request); err != nil { badRequestErr := customErrors.NewBadRequestErrorWrap( err, - "[searchProductsEndpoint_handler.Bind] error in the binding request", - ) - ep.Logger.Errorf( - fmt.Sprintf("[searchProductsEndpoint_handler.Bind] err: %v", badRequestErr), + "error in the binding request", ) + return badRequestErr } @@ -82,9 +73,9 @@ func (ep *searchProductsEndpoint) handler() echo.HandlerFunc { if err := query.Validate(); err != nil { validationErr := customErrors.NewValidationErrorWrap( err, - "[searchProductsEndpoint_handler.StructCtx] query validation failed", + "query validation failed", ) - ep.Logger.Errorf("[searchProductsEndpoint_handler.StructCtx] err: {%v}", validationErr) + return validationErr } @@ -93,12 +84,10 @@ func (ep *searchProductsEndpoint) handler() echo.HandlerFunc { query, ) if err != nil { - err = errors.WithMessage( + return errors.WithMessage( err, - "[searchProductsEndpoint_handler.Send] error in sending SearchProducts", + "error in sending SearchProducts", ) - ep.Logger.Error(fmt.Sprintf("[searchProductsEndpoint_handler.Send] err: {%v}", err)) - return err } return c.JSON(http.StatusOK, queryResult) diff --git a/internal/services/catalog_read_service/internal/products/features/searching_products/v1/queries/search_products_handler.go b/internal/services/catalog_read_service/internal/products/features/searching_products/v1/queries/search_products_handler.go index abbf5cbc..c5ba5375 100644 --- a/internal/services/catalog_read_service/internal/products/features/searching_products/v1/queries/search_products_handler.go +++ b/internal/services/catalog_read_service/internal/products/features/searching_products/v1/queries/search_products_handler.go @@ -6,8 +6,6 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" - utils2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/dto" @@ -25,39 +23,39 @@ func NewSearchProductsHandler( repository data.ProductRepository, tracer tracing.AppTracer, ) *SearchProductsHandler { - return &SearchProductsHandler{log: log, mongoRepository: repository, tracer: tracer} + return &SearchProductsHandler{ + log: log, + mongoRepository: repository, + tracer: tracer, + } } func (c *SearchProductsHandler) Handle( ctx context.Context, query *SearchProducts, ) (*dtos.SearchProductsResponseDto, error) { - ctx, span := c.tracer.Start(ctx, "SearchProductsHandler.Handle") - span.SetAttributes(attribute.Object("Query", query)) - defer span.End() - - products, err := c.mongoRepository.SearchProducts(ctx, query.SearchText, query.ListQuery) + products, err := c.mongoRepository.SearchProducts( + ctx, + query.SearchText, + query.ListQuery, + ) if err != nil { - return nil, utils2.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[SearchProductsHandler_Handle.SearchProducts] error in searching products in the repository", - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in searching products in the repository", ) } - listResultDto, err := utils.ListResultToListResultDto[*dto.ProductDto](products) + listResultDto, err := utils.ListResultToListResultDto[*dto.ProductDto]( + products, + ) if err != nil { - return nil, utils2.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[SearchProductsHandler_Handle.ListResultToListResultDto] error in the mapping ListResultToListResultDto", - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in the mapping ListResultToListResultDto", ) } - c.log.Info("[SearchProductsHandler.Handle] products fetched") + c.log.Info("products fetched") return &dtos.SearchProductsResponseDto{Products: listResultDto}, nil } diff --git a/internal/services/catalog_read_service/internal/products/features/updating_products/v1/commands/update_product_handler.go b/internal/services/catalog_read_service/internal/products/features/updating_products/v1/commands/update_product_handler.go index 1ef5f9c2..4ccb786e 100644 --- a/internal/services/catalog_read_service/internal/products/features/updating_products/v1/commands/update_product_handler.go +++ b/internal/services/catalog_read_service/internal/products/features/updating_products/v1/commands/update_product_handler.go @@ -7,12 +7,9 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" "github.com/mehdihadeli/go-mediatr" - attribute2 "go.opentelemetry.io/otel/attribute" ) type UpdateProductHandler struct { @@ -40,34 +37,26 @@ func (c *UpdateProductHandler) Handle( ctx context.Context, command *UpdateProduct, ) (*mediatr.Unit, error) { - ctx, span := c.tracer.Start(ctx, "UpdateProductHandler.Handle") - span.SetAttributes(attribute2.String("ProductId", command.ProductId.String())) - span.SetAttributes(attribute.Object("Command", command)) - defer span.End() - - product, err := c.mongoRepository.GetProductByProductId(ctx, command.ProductId.String()) + product, err := c.mongoRepository.GetProductByProductId( + ctx, + command.ProductId.String(), + ) if err != nil { - return nil, utils.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - fmt.Sprintf( - "[UpdateProductHandler_Handle.GetProductById] error in fetching product with productId %s in the mongo repository", - command.ProductId, - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + fmt.Sprintf( + "error in fetching product with productId %s in the mongo repository", + command.ProductId, ), ) } if product == nil { - return nil, utils.TraceErrFromSpan( - span, - customErrors.NewNotFoundErrorWrap( - err, - fmt.Sprintf( - "[UpdateProductHandler_Handle.GetProductById] product with productId %s not found", - command.ProductId, - ), + return nil, customErrors.NewNotFoundErrorWrap( + err, + fmt.Sprintf( + "product with productId %s not found", + command.ProductId, ), ) } @@ -79,28 +68,25 @@ func (c *UpdateProductHandler) Handle( _, err = c.mongoRepository.UpdateProduct(ctx, product) if err != nil { - return nil, utils.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[UpdateProductHandler_Handle.UpdateProduct] error in updating product in the mongo repository", - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in updating product in the mongo repository", ) } err = c.redisRepository.PutProduct(ctx, product.Id, product) if err != nil { - return nil, utils.TraceErrFromSpan( - span, - customErrors.NewApplicationErrorWrap( - err, - "[UpdateProductHandler_Handle.PutProduct] error in updating product in the redis repository", - ), + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in updating product in the redis repository", ) } c.log.Infow( - fmt.Sprintf("[UpdateProductHandler.Handle] product with id: {%s} updated", product.Id), + fmt.Sprintf( + "product with id: {%s} updated", + product.Id, + ), logger.Fields{"ProductId": command.ProductId, "Id": product.Id}, ) diff --git a/internal/services/catalog_read_service/internal/products/products_fx.go b/internal/services/catalog_read_service/internal/products/products_fx.go index 3be53eaf..5fe53c96 100644 --- a/internal/services/catalog_read_service/internal/products/products_fx.go +++ b/internal/services/catalog_read_service/internal/products/products_fx.go @@ -1,8 +1,8 @@ package products import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/data/repositories" getProductByIdV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/endpoints" getProductsV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/getting_products/v1/endpoints" diff --git a/internal/services/catalog_read_service/internal/shared/app/application.go b/internal/services/catalog_read_service/internal/shared/app/application.go index 4ff43358..bd2e0ce3 100644 --- a/internal/services/catalog_read_service/internal/shared/app/application.go +++ b/internal/services/catalog_read_service/internal/shared/app/application.go @@ -1,7 +1,7 @@ package app import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/configurations/catalogs" @@ -18,7 +18,7 @@ func NewCatalogsReadApplication( decorates []interface{}, options []fx.Option, logger logger.Logger, - environment environemnt.Environment, + environment environment.Environment, ) *CatalogsReadApplication { app := fxapp.NewApplication(providers, decorates, options, logger, environment) return &CatalogsReadApplication{ diff --git a/internal/services/catalog_read_service/internal/shared/app/test/test_application.go b/internal/services/catalog_read_service/internal/shared/app/test/test_application.go index e093ff9d..04b63352 100644 --- a/internal/services/catalog_read_service/internal/shared/app/test/test_application.go +++ b/internal/services/catalog_read_service/internal/shared/app/test/test_application.go @@ -1,7 +1,7 @@ package test import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/test" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/app" @@ -22,7 +22,7 @@ func NewCatalogsReadTestApplication( decorates []interface{}, options []fx.Option, logger logger.Logger, - environment environemnt.Environment, + environment environment.Environment, ) *CatalogsReadTestApplication { testApp := test.NewTestApplication( tb, diff --git a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go b/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go index 54fcd8e9..35130df2 100644 --- a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go +++ b/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go @@ -5,9 +5,9 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/pipelines" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" - pipelines2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/pipelines" + pipelines2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/mediatr/pipelines" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - tracingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/pipelines" + tracingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/mediatr/pipelines" "github.com/mehdihadeli/go-mediatr" ) @@ -29,11 +29,11 @@ func (ic *InfrastructureConfigurator) ConfigInfrastructures() { func(logger logger.Logger, tracer tracing.AppTracer, metrics metrics.AppMetrics) error { err := mediatr.RegisterRequestPipelineBehaviors( pipelines.NewLoggingPipeline(logger), - tracingpipelines.NewTracingPipeline( + tracingpipelines.NewMediatorTracingPipeline( tracer, tracingpipelines.WithLogger(logger), ), - pipelines2.NewMetricsPipeline( + pipelines2.NewMediatorMetricsPipeline( metrics, pipelines2.WithLogger(logger), ), diff --git a/internal/services/catalog_read_service/internal/shared/contracts/catalogs_metrics.go b/internal/services/catalog_read_service/internal/shared/contracts/catalogs_metrics.go index f6701e6a..7db30b63 100644 --- a/internal/services/catalog_read_service/internal/shared/contracts/catalogs_metrics.go +++ b/internal/services/catalog_read_service/internal/shared/contracts/catalogs_metrics.go @@ -10,12 +10,6 @@ type CatalogsMetrics struct { DeleteProductGrpcRequests metric.Float64Counter GetProductByIdGrpcRequests metric.Float64Counter SearchProductGrpcRequests metric.Float64Counter - CreateProductHttpRequests metric.Float64Counter - UpdateProductHttpRequests metric.Float64Counter - DeleteProductHttpRequests metric.Float64Counter - GetProductByIdHttpRequests metric.Float64Counter - GetProductsHttpRequests metric.Float64Counter - SearchProductHttpRequests metric.Float64Counter SuccessRabbitMQMessages metric.Float64Counter ErrorRabbitMQMessages metric.Float64Counter CreateProductRabbitMQMessages metric.Float64Counter diff --git a/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/commands/create_product_test.go b/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/commands/create_product_test.go index e4db5731..5486a625 100644 --- a/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/commands/create_product_test.go +++ b/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/commands/create_product_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/commands" + v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/test_fixture/integration" @@ -32,7 +32,7 @@ func TestCreateProduct(t *testing.T) { "Creating a new product and saving it to the database for a none-existing product", func() { Convey("Given new product doesn't exists in the system", func() { - command, err := commands.NewCreateProduct( + command, err := v1.NewCreateProduct( uuid.NewV4().String(), gofakeit.Name(), gofakeit.AdjectiveDescriptive(), @@ -44,7 +44,7 @@ func TestCreateProduct(t *testing.T) { Convey( "When the CreateProduct command is executed and product doesn't exists", func() { - result, err := mediatr.Send[*commands.CreateProduct, *dtos.CreateProductResponseDto]( + result, err := mediatr.Send[*v1.CreateProduct, *dtos.CreateProductResponseDto]( ctx, command, ) diff --git a/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/events/product_created_test.go b/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/events/product_created_test.go index 65bf888d..c6acd362 100644 --- a/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/events/product_created_test.go +++ b/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/events/product_created_test.go @@ -13,7 +13,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging" testUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/utils" - externalEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/events/integration_events/external_events" + externalEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/events/integrationevents/externalevents" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/test_fixture/integration" diff --git a/internal/services/catalog_write_service/cmd/migration/main.go b/internal/services/catalog_write_service/cmd/migration/main.go index fd0b4284..8cf6b1b6 100644 --- a/internal/services/catalog_write_service/cmd/migration/main.go +++ b/internal/services/catalog_write_service/cmd/migration/main.go @@ -5,7 +5,7 @@ import ( "os" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" @@ -70,7 +70,7 @@ func executeMigration(cmd *cobra.Command, commandType migration.CommandType) { } app := fx.New( - config.ModuleFunc(environemnt.Development), + config.ModuleFunc(environment.Development), zap.Module, fxlog.FxLogger, gormPostgres.Module, diff --git a/internal/services/catalog_write_service/config/app_options.go b/internal/services/catalog_write_service/config/app_options.go index b2e3ce78..1f4c65ba 100644 --- a/internal/services/catalog_write_service/config/app_options.go +++ b/internal/services/catalog_write_service/config/app_options.go @@ -4,7 +4,7 @@ import ( "strings" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" "github.com/iancoleman/strcase" @@ -15,7 +15,7 @@ type AppOptions struct { ServiceName string `mapstructure:"serviceName" env:"serviceName"` } -func NewAppOptions(environment environemnt.Environment) (*AppOptions, error) { +func NewAppOptions(environment environment.Environment) (*AppOptions, error) { optionName := strcase.ToLowerCamel(typeMapper.GetTypeNameByT[AppOptions]()) cfg, err := config.BindConfigKey[*AppOptions](optionName, environment) if err != nil { diff --git a/internal/services/catalog_write_service/config/config.development.json b/internal/services/catalog_write_service/config/config.development.json index 325aa5c2..f3719637 100644 --- a/internal/services/catalog_write_service/config/config.development.json +++ b/internal/services/catalog_write_service/config/config.development.json @@ -100,9 +100,6 @@ "serviceName": "catalogs-write-service", "instrumentationName": "io.opentelemetry.metrics.catalogs-write-service" }, - "eventStoreDbOptions": { - "connectionString": "esdb://localhost:2113?tls=false" - }, "migrationOptions": { "host": "localhost", "port": 5432, diff --git a/internal/services/catalog_write_service/config/config.test.json b/internal/services/catalog_write_service/config/config.test.json index 45fdc4de..a3bbbe20 100644 --- a/internal/services/catalog_write_service/config/config.test.json +++ b/internal/services/catalog_write_service/config/config.test.json @@ -76,9 +76,6 @@ "serviceName": "catalogs-write-service", "instrumentationName": "io.opentelemetry.metrics.catalogs-write-service" }, - "eventStoreDbOptions": { - "connectionString": "esdb://localhost:2113?tls=false" - }, "migrationOptions": { "host": "localhost", "port": 5432, diff --git a/internal/services/catalog_write_service/go.mod b/internal/services/catalog_write_service/go.mod index 36bb9f9a..5c2c21f2 100644 --- a/internal/services/catalog_write_service/go.mod +++ b/internal/services/catalog_write_service/go.mod @@ -16,7 +16,7 @@ require ( github.com/labstack/echo/v4 v4.11.1 github.com/lib/pq v1.10.9 github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg v0.0.0-20230831075934-be8df319f588 - github.com/mehdihadeli/go-mediatr v1.2.0 + github.com/mehdihadeli/go-mediatr v1.3.0 github.com/michaelklishin/rabbit-hole v1.5.0 github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.28.0 @@ -43,7 +43,6 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/ClickHouse/ch-go v0.58.2 // indirect github.com/ClickHouse/clickhouse-go/v2 v2.14.1 // indirect - github.com/EventStore/EventStore-Client-Go v1.0.2 // indirect github.com/KyleBanks/depth v1.2.1 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect @@ -83,11 +82,9 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-testfixtures/testfixtures/v3 v3.9.0 // indirect github.com/goccy/go-reflect v1.2.0 // indirect - github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang-migrate/migrate/v4 v4.16.2 // indirect - github.com/golang/mock v1.6.0 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/go-querystring v1.1.0 // indirect @@ -164,13 +161,14 @@ require ( github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect + github.com/ulule/limiter/v3 v3.11.2 // indirect github.com/uptrace/bun v1.1.16 // indirect github.com/uptrace/bun/driver/pgdriver v1.1.16 // indirect github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.3 // indirect github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3 // indirect github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.27.0 // indirect + github.com/valyala/fasthttp v1.47.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect github.com/vmihailenco/msgpack/v5 v5.4.0 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect @@ -216,6 +214,7 @@ require ( golang.org/x/tools v0.13.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect + gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gorm.io/driver/postgres v1.5.2 // indirect gorm.io/plugin/opentelemetry v0.1.4 // indirect diff --git a/internal/services/catalog_write_service/go.sum b/internal/services/catalog_write_service/go.sum index 5a7f4c18..0fdb0737 100644 --- a/internal/services/catalog_write_service/go.sum +++ b/internal/services/catalog_write_service/go.sum @@ -6,7 +6,6 @@ atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8= atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ= atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs= atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU= -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -56,7 +55,6 @@ emperror.dev/errors v0.8.1 h1:UavXZ5cSX/4u9iyvH6aDcuGkVjeexUGJ7Ij7G4VfQT0= emperror.dev/errors v0.8.1/go.mod h1:YcRvLPh626Ubn2xqtoprejnA5nFha+TJ+2vew48kWuE= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -67,8 +65,6 @@ github.com/ClickHouse/clickhouse-go/v2 v2.14.1 h1:5C2hhmZEGUVdy8CPpY3iPpfBv2kRbx github.com/ClickHouse/clickhouse-go/v2 v2.14.1/go.mod h1:PHqbMvJTQ0EI4a1vJhmbmL/Ajr+Cin2O+WJjnYctJvg= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/EventStore/EventStore-Client-Go v1.0.2 h1:onM2TIInLhWUJwUQ/5a/8blNrrbhwrtm7Tpmg13ohiw= -github.com/EventStore/EventStore-Client-Go v1.0.2/go.mod h1:NOqSOtNxqGizr1Qnf7joGGLK6OkeoLV/QEI893A43H0= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= @@ -84,13 +80,10 @@ github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030I github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.1 h1:hJ3s7GbWlGK4YVV92sO88BQSyF4ZLVy7/awqOlPxFbA= github.com/Microsoft/hcsshim v0.11.1/go.mod h1:nFJmaO4Zr5Y7eADdFOpYswDDlNVbvcIJJNJLECr5JQg= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2/go.mod h1:VSw57q4QFiWDbRnjdX8Cb3Ow0SFncRw+bA/ofY6Q83w= github.com/ahmetb/go-linq/v3 v3.2.0 h1:BEuMfp+b59io8g5wYzNoFe9pWPalRklhlhbiU3hYZDE= @@ -122,17 +115,14 @@ github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/caarlos0/env/v8 v8.0.0 h1:POhxHhSpuxrLMIdvTGARuZqR4Jjm8AYmoi/JKlcScs0= github.com/caarlos0/env/v8 v8.0.0/go.mod h1:7K4wMY9bH0esiXSSHlfHLX5xKGQMnkH5Fk4TDSSSzfo= -github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -141,27 +131,19 @@ github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+g github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/containerd v1.7.6 h1:oNAVsnhPoy4BTPQivLgTzI9Oleml9l/+eYIDYXRCYo8= github.com/containerd/containerd v1.7.6/go.mod h1:SY6lrkkuJT40BVNO37tlYTSnKJnP5AXBc0fhx0q+TJ4= -github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= -github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= -github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.1/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -170,20 +152,16 @@ github.com/denisenkom/go-mssqldb v0.12.3 h1:pBSGx9Tq67pBOTLmxNuirNTeB8Vjmf886Kx+ github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDrorD1Vrm1KEz5hxDo= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY= -github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE= github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/doug-martin/goqu/v9 v9.18.0 h1:/6bcuEtAe6nsSMVK/M+fOiXUNfyFF3yYtE07DBPFMYY= github.com/doug-martin/goqu/v9 v9.18.0/go.mod h1:nf0Wc2/hV3gYK9LiyqIrzBEVGlI8qW3GuDCEobC4wBQ= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -200,7 +178,6 @@ github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/structs v1.0.0 h1:BrX964Rv5uQ3wwS+KRUAJCBBw5PQmgJfJ6v4yly5QwU= github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -264,8 +241,6 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-reflect v1.2.0 h1:O0T8rZCuNmGXewnATuKYnkL0xm6o8UNOJZd/gOkb9ms= github.com/goccy/go-reflect v1.2.0/go.mod h1:n0oYZn8VcV2CkWTxi8B9QjkCoq6GTtCEdfmR66YhFtE= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= @@ -293,8 +268,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -350,8 +323,6 @@ github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ= github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= @@ -363,8 +334,6 @@ github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQ github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= -github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e h1:XmA6L9IPRdUr28a+SK/oMchGgQy159wvzXA5tJ7l+40= -github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e/go.mod h1:AFIo+02s+12CEg8Gzz9kzhCbmbq6JcKNrhHffCGA9z4= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= @@ -386,11 +355,8 @@ github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSAS github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/imkira/go-interpol v1.0.0 h1:HrmLyvOLJyjR0YofMw8QGdCIuYOs4TJUBDNU5sJC09E= github.com/imkira/go-interpol v1.0.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= @@ -495,11 +461,9 @@ github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhR github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= -github.com/lib/pq v0.0.0-20180327071824-d34b9ff171c2/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= @@ -540,20 +504,16 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mcuadros/go-defaults v1.2.0 h1:FODb8WSf0uGaY8elWJAkoLL0Ri6AlZ1bFlenk56oZtc= github.com/mcuadros/go-defaults v1.2.0/go.mod h1:WEZtHEVIGYVDqkKSWBdWKUVdRyKlMfulPaGDWIVeCWY= -github.com/mehdihadeli/go-mediatr v1.1.10 h1:NAzg4065c90lgYeb+Vzbd2WKH0tUFpxzL0mpx6hkU/A= -github.com/mehdihadeli/go-mediatr v1.1.10/go.mod h1:lwgZl7qVL/RKomObBblhG3uEte/r4nJDV95Vd+nGrMw= -github.com/mehdihadeli/go-mediatr v1.2.0 h1:XkzYF/uGfW4pwPWYAxKyY+mO6l989PbmCQWSYHuCZtU= -github.com/mehdihadeli/go-mediatr v1.2.0/go.mod h1:I9LuExxAKz6cTDJyP/SSDSmkHaPHK1/usnvEXjUY47k= +github.com/mehdihadeli/go-mediatr v1.3.0 h1:hrb5Scp/nsiR3Y62mjZ0Tc5UX/dRJl4nDFkINBEIESA= +github.com/mehdihadeli/go-mediatr v1.3.0/go.mod h1:lsG+hyH+pEOhmZiZl0KPO72BcZiEReF03CBk4GVJB0k= github.com/michaelklishin/rabbit-hole v1.5.0 h1:Bex27BiFDsijCM9D0ezSHqyy0kehpYHuNKaPqq/a4RM= github.com/michaelklishin/rabbit-hole v1.5.0/go.mod h1:vvI1uOitYZi0O5HEGXhaWC1XT80Gy+HvFheJ+5Krlhk= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= -github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= -github.com/moby/term v0.0.0-20200915141129-7f0af18e79f2/go.mod h1:TjQg8pa4iejrUrjiz0MCtMV38jdMNW4doKSiBrEvCQQ= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= @@ -561,7 +521,6 @@ github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8 github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nolleh/caption_json_formatter v0.2.2 h1:EKsOr/fCllNQF2ZoajfbSDlV73BNV1bDu1aTTSRrlN0= github.com/nolleh/caption_json_formatter v0.2.2/go.mod h1:5FYofZA8NAej/eFxa12FvyQKosU1LfyKizZPlY0JojU= @@ -580,24 +539,15 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.28.0 h1:i2rg/p9n/UqIDAMFUJ6qIUUMcsqOuUHgbpbu235Vr1c= github.com/onsi/gomega v1.28.0/go.mod h1:A1H2JE76sI14WIP57LMKj7FVfCHx3g3BcZVjJG8bjX8= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc95/go.mod h1:z+bZxa/+Tz/FmYVWkhUajJdzFeOqjc5vrqskhVyHGUM= github.com/opencontainers/runc v1.1.9 h1:XR0VIHTGce5eWPkaPesqTBrhW2yAcaraWfsEalNwQLM= github.com/opencontainers/runc v1.1.9/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.4.2 h1:zjqfqHjUpPmB3c1GlCvvgsM1G4LkvqQbBDueDOCg/jA= github.com/openzipkin/zipkin-go v0.4.2/go.mod h1:ZeVkFjuuBiSy13y8vpSDCjMi9GoI3hPpCJSBx/EYFhY= -github.com/ory/dockertest/v3 v3.6.3/go.mod h1:EFLcVUOl8qCwp9NyDAcCDtq/QviLtYswW/VbWzUnTNE= -github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4= -github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg= github.com/paulmach/orb v0.10.0 h1:guVYVqzxHE/CQ1KpfGO077TR0ATHSNjp4s6XGLn3W9s= github.com/paulmach/orb v0.10.0/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= @@ -605,7 +555,6 @@ github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6 github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -655,7 +604,6 @@ github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncj github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= @@ -663,7 +611,6 @@ github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/savsgio/gotils v0.0.0-20210617111740-97865ed5a873 h1:N3Af8f13ooDKcIhsmFT7Z05CStZWu4C7Md0uDEy4q6o= github.com/savsgio/gotils v0.0.0-20210617111740-97865ed5a873/go.mod h1:dmPawKuiAeG/aFYVs2i+Dyosoo7FNcm+Pi8iK6ZUrX8= -github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= @@ -679,24 +626,18 @@ github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9Nz github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= -github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= @@ -730,7 +671,6 @@ github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM= github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04= github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/testcontainers/testcontainers-go v0.25.0 h1:erH6cQjsaJrH+rJDU9qIf89KFdhK0Bft0aEZHlYC3Vs= github.com/testcontainers/testcontainers-go v0.25.0/go.mod h1:4sC9SiJyzD1XFi59q8umTQYWxnkweEc5OjVtTUlJzqQ= github.com/testcontainers/testcontainers-go/modules/postgres v0.25.0 h1:8WNK1Edo9ohRYPrDCXWdoVY2cbg/oFh9y5uWZGSBESo= @@ -742,6 +682,8 @@ github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+F github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= +github.com/ulule/limiter/v3 v3.11.2 h1:P4yOrxoEMJbOTfRJR2OzjL90oflzYPPmWg+dvwN2tHA= +github.com/ulule/limiter/v3 v3.11.2/go.mod h1:QG5GnFOCV+k7lrL5Y8kgEeeflPH3+Cviqlqa8SVSQxI= github.com/uptrace/bun v1.1.16 h1:cn9cgEMFwcyYRsQLfxCRMUxyK1WaHwOVrR3TvzEFZ/A= github.com/uptrace/bun v1.1.16/go.mod h1:7HnsMRRvpLFUcquJxp22JO8PsWKpFQO/gNXqqsuGWg8= github.com/uptrace/bun/driver/pgdriver v1.1.16 h1:b/NiSXk6Ldw7KLfMLbOqIkm4odHd7QiNOCPLqPFJjK4= @@ -752,22 +694,19 @@ github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3 h1:LyGS9cIZV0YVhE81zwf github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3/go.mod h1:RvCYhPchLhvQ9l9C9goblbgO7BaKt597kBMf5mgKyo0= github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3 h1:2na5W81H38Z4qXCQCuzlcdSMiTWgPJ6XeZIArq6VIJE= github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3/go.mod h1:9IVEh9mPv3NwFf99dVLX15FqVgdpZJ8RMDo/Cr0vK74= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.27.0 h1:gDefRDL9aqSiwXV6aRW8aSBPs82y4KizSzHrBLf4NDI= github.com/valyala/fasthttp v1.27.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA= +github.com/valyala/fasthttp v1.47.0 h1:y7moDoxYzMooFpT5aHgNgVOQDrS3qlkfiP9mDtGGK9c= +github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vmihailenco/msgpack/v5 v5.4.0 h1:hRM0digJwyR6vll33NNAwCFguy5JuBD6jxDmQP3l608= github.com/vmihailenco/msgpack/v5 v5.4.0/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= @@ -804,7 +743,6 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= @@ -882,7 +820,6 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= @@ -939,7 +876,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= @@ -958,7 +894,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -979,7 +914,6 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -1024,7 +958,6 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1033,7 +966,6 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1051,9 +983,7 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1066,8 +996,6 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1129,7 +1057,6 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1174,7 +1101,6 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= @@ -1241,7 +1167,6 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1289,7 +1214,6 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1298,7 +1222,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= @@ -1311,7 +1234,6 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -1329,7 +1251,6 @@ gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gorm.io/plugin/opentelemetry v0.1.4 h1:7p0ocWELjSSRI7NCKPW2mVe6h43YPini99sNJcbsTuc= gorm.io/plugin/opentelemetry v0.1.4/go.mod h1:tndJHOdvPT0pyGhOb8E2209eXJCUxhC5UpKw7bGVWeI= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/services/catalog_write_service/internal/products/configurations/endpoints/endpoints.go b/internal/services/catalog_write_service/internal/products/configurations/endpoints/endpoints.go new file mode 100644 index 00000000..d4e283a4 --- /dev/null +++ b/internal/services/catalog_write_service/internal/products/configurations/endpoints/endpoints.go @@ -0,0 +1,13 @@ +package endpoints + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" +) + +func RegisterEndpoints(endpoints []route.Endpoint) error { + for _, endpoint := range endpoints { + endpoint.MapEndpoint() + } + + return nil +} diff --git a/internal/services/catalog_write_service/internal/products/configurations/mappings/mapping_profile.go b/internal/services/catalog_write_service/internal/products/configurations/mappings/mapping_profile.go index bf93fb6a..0a1ba308 100644 --- a/internal/services/catalog_write_service/internal/products/configurations/mappings/mapping_profile.go +++ b/internal/services/catalog_write_service/internal/products/configurations/mappings/mapping_profile.go @@ -2,7 +2,7 @@ package mappings import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" + dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" productsService "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/grpc/genproto" diff --git a/internal/services/catalog_write_service/internal/products/configurations/mediator/mediator.go b/internal/services/catalog_write_service/internal/products/configurations/mediator/mediator.go new file mode 100644 index 00000000..32a1acb2 --- /dev/null +++ b/internal/services/catalog_write_service/internal/products/configurations/mediator/mediator.go @@ -0,0 +1,14 @@ +package mediator + +import "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" + +func RegisterMediatorHandlers(handlers []cqrs.HandlerRegisterer) error { + for _, handler := range handlers { + err := handler.RegisterHandler() + if err != nil { + return err + } + } + + return nil +} diff --git a/internal/services/catalog_write_service/internal/products/configurations/mediatr/mediator_configurations.go b/internal/services/catalog_write_service/internal/products/configurations/mediatr/mediator_configurations.go deleted file mode 100644 index e1df43a5..00000000 --- a/internal/services/catalog_write_service/internal/products/configurations/mediatr/mediator_configurations.go +++ /dev/null @@ -1,73 +0,0 @@ -package mediatr - -import ( - logger2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" - createProductCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/commands" - createProductV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/dtos" - deleteProductCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1/commands" - getProductByIdDtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/dtos" - getProductByIdQueryV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/queries" - getProductsDtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/dtos" - getProductsQueryV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/queries" - searchProductsDtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searching_product/v1/dtos" - searchProductsQueryV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searching_product/v1/queries" - updateProductCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/commands" - - "github.com/mehdihadeli/go-mediatr" -) - -func ConfigProductsMediator( - logger logger2.Logger, - uow data.CatalogUnitOfWork, - productRepository data.ProductRepository, - producer producer.Producer, - tracer tracing.AppTracer, -) error { - // https://stackoverflow.com/questions/72034479/how-to-implement-generic-interfaces - err := mediatr.RegisterRequestHandler[*createProductCommandV1.CreateProduct, *createProductV1.CreateProductResponseDto]( - createProductCommandV1.NewCreateProductHandler(logger, uow, producer, tracer), - ) - if err != nil { - return err - } - - err = mediatr.RegisterRequestHandler[*getProductsQueryV1.GetProducts, *getProductsDtosV1.GetProductsResponseDto]( - getProductsQueryV1.NewGetProductsHandler(logger, productRepository, tracer), - ) - if err != nil { - return err - } - - err = mediatr.RegisterRequestHandler[*searchProductsQueryV1.SearchProducts, *searchProductsDtosV1.SearchProductsResponseDto]( - searchProductsQueryV1.NewSearchProductsHandler(logger, productRepository, tracer), - ) - if err != nil { - return err - } - - err = mediatr.RegisterRequestHandler[*updateProductCommandV1.UpdateProduct, *mediatr.Unit]( - updateProductCommandV1.NewUpdateProductHandler(logger, uow, producer, tracer), - ) - if err != nil { - return err - } - - err = mediatr.RegisterRequestHandler[*deleteProductCommandV1.DeleteProduct, *mediatr.Unit]( - deleteProductCommandV1.NewDeleteProductHandler(logger, uow, producer, tracer), - ) - if err != nil { - return err - } - - err = mediatr.RegisterRequestHandler[*getProductByIdQueryV1.GetProductById, *getProductByIdDtosV1.GetProductByIdResponseDto]( - getProductByIdQueryV1.NewGetProductByIdHandler(logger, productRepository, tracer), - ) - if err != nil { - return err - } - - return nil -} diff --git a/internal/services/catalog_write_service/internal/products/configurations/products_module_configurator.go b/internal/services/catalog_write_service/internal/products/configurations/products_module_configurator.go index e5ee7b47..396d8af8 100644 --- a/internal/services/catalog_write_service/internal/products/configurations/products_module_configurator.go +++ b/internal/services/catalog_write_service/internal/products/configurations/products_module_configurator.go @@ -1,15 +1,11 @@ package configurations import ( - contracts2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" + fxcontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" grpcServer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations/endpoints" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations/mappings" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations/mediatr" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/params" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations/mediator" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/grpc" productsservice "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/grpc/genproto" @@ -17,53 +13,54 @@ import ( ) type ProductsModuleConfigurator struct { - contracts2.Application + fxcontracts.Application } func NewProductsModuleConfigurator( - fxapp contracts2.Application, + fxapp fxcontracts.Application, ) *ProductsModuleConfigurator { return &ProductsModuleConfigurator{ Application: fxapp, } } -func (c *ProductsModuleConfigurator) ConfigureProductsModule() { - c.ResolveFunc( - func(logger logger.Logger, uow data.CatalogUnitOfWork, productRepository data.ProductRepository, producer producer.Producer, tracer tracing.AppTracer) error { - // config Products Mediators - err := mediatr.ConfigProductsMediator(logger, uow, productRepository, producer, tracer) - if err != nil { - return err - } - - // cfg Products Mappings - err = mappings.ConfigureProductsMappings() - if err != nil { - return err - } +func (c *ProductsModuleConfigurator) ConfigureProductsModule() error { + // config products mappings + err := mappings.ConfigureProductsMappings() + if err != nil { + return err + } - return nil - }, + // register products request handler on mediator + c.ResolveFuncWithParamTag( + mediator.RegisterMediatorHandlers, + `group:"product-handlers"`, ) + + return nil } -func (c *ProductsModuleConfigurator) MapProductsEndpoints() { - // config Products Http Endpoints - c.ResolveFunc(func(endpointParams params.ProductsEndpointsParams) { - for _, endpoint := range endpointParams.Endpoints { - endpoint.MapEndpoint() - } - }) +func (c *ProductsModuleConfigurator) MapProductsEndpoints() error { + // config endpoints + c.ResolveFuncWithParamTag( + endpoints.RegisterEndpoints, + `group:"product-routes"`, + ) // config Products Grpc Endpoints c.ResolveFunc( func(catalogsGrpcServer grpcServer.GrpcServer, grpcService *grpc.ProductGrpcServiceServer) error { - catalogsGrpcServer.GrpcServiceBuilder().RegisterRoutes(func(server *googleGrpc.Server) { - productsservice.RegisterProductsServiceServer(server, grpcService) - }) + catalogsGrpcServer.GrpcServiceBuilder(). + RegisterRoutes(func(server *googleGrpc.Server) { + productsservice.RegisterProductsServiceServer( + server, + grpcService, + ) + }) return nil }, ) + + return nil } diff --git a/internal/services/catalog_write_service/internal/products/configurations/rabbitmq/rabbitmq_configurations.go b/internal/services/catalog_write_service/internal/products/configurations/rabbitmq/rabbitmq_configurations.go index d5fa1ab3..8f982ba0 100644 --- a/internal/services/catalog_write_service/internal/products/configurations/rabbitmq/rabbitmq_configurations.go +++ b/internal/services/catalog_write_service/internal/products/configurations/rabbitmq/rabbitmq_configurations.go @@ -3,12 +3,15 @@ package rabbitmq import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" producerConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/configurations" - createProductIntegrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/events/integration_events" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/events/integrationevents" ) -func ConfigProductsRabbitMQ(builder configurations.RabbitMQConfigurationBuilder) { +func ConfigProductsRabbitMQ( + builder configurations.RabbitMQConfigurationBuilder, +) { builder.AddProducer( - createProductIntegrationEvents.ProductCreatedV1{}, + integrationevents.ProductCreatedV1{}, func(builder producerConfigurations.RabbitMQProducerConfigurationBuilder) { - }) + }, + ) } diff --git a/internal/services/catalog_write_service/internal/products/contracts/data/catalog_unit_of_work.go b/internal/services/catalog_write_service/internal/products/contracts/catalog_unit_of_work.go similarity index 94% rename from internal/services/catalog_write_service/internal/products/contracts/data/catalog_unit_of_work.go rename to internal/services/catalog_write_service/internal/products/contracts/catalog_unit_of_work.go index 44d4f22a..cd555b8e 100644 --- a/internal/services/catalog_write_service/internal/products/contracts/data/catalog_unit_of_work.go +++ b/internal/services/catalog_write_service/internal/products/contracts/catalog_unit_of_work.go @@ -1,4 +1,4 @@ -package data +package contracts import "context" diff --git a/internal/services/catalog_write_service/internal/products/contracts/data/catalogs_context.go b/internal/services/catalog_write_service/internal/products/contracts/catalogs_context.go similarity index 93% rename from internal/services/catalog_write_service/internal/products/contracts/data/catalogs_context.go rename to internal/services/catalog_write_service/internal/products/contracts/catalogs_context.go index adf3fc9c..71c0e83f 100644 --- a/internal/services/catalog_write_service/internal/products/contracts/data/catalogs_context.go +++ b/internal/services/catalog_write_service/internal/products/contracts/catalogs_context.go @@ -1,4 +1,4 @@ -package data +package contracts // CatalogContext provides access to datastores that can be // used inside a Unit-of-Work. All data changes done through diff --git a/internal/services/catalog_write_service/internal/products/contracts/params/product_endpoints_param.go b/internal/services/catalog_write_service/internal/products/contracts/params/product_endpoints_param.go deleted file mode 100644 index ee29e693..00000000 --- a/internal/services/catalog_write_service/internal/products/contracts/params/product_endpoints_param.go +++ /dev/null @@ -1,13 +0,0 @@ -package params - -import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" - - "go.uber.org/fx" -) - -type ProductsEndpointsParams struct { - fx.In - - Endpoints []route.Endpoint `group:"product-routes"` -} diff --git a/internal/services/catalog_write_service/internal/products/contracts/data/product_repository.go b/internal/services/catalog_write_service/internal/products/contracts/product_repository.go similarity index 97% rename from internal/services/catalog_write_service/internal/products/contracts/data/product_repository.go rename to internal/services/catalog_write_service/internal/products/contracts/product_repository.go index a9c1b347..aff647d7 100644 --- a/internal/services/catalog_write_service/internal/products/contracts/data/product_repository.go +++ b/internal/services/catalog_write_service/internal/products/contracts/product_repository.go @@ -1,4 +1,4 @@ -package data +package contracts import ( "context" diff --git a/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go b/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go index fc7443af..b9b9ba82 100644 --- a/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go +++ b/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go @@ -11,7 +11,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" utils2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - data2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" + data2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "emperror.dev/errors" diff --git a/internal/services/catalog_write_service/internal/products/data/uow/catalog_context.go b/internal/services/catalog_write_service/internal/products/data/uow/catalog_context.go index cfc0a8c8..bf4090ef 100644 --- a/internal/services/catalog_write_service/internal/products/data/uow/catalog_context.go +++ b/internal/services/catalog_write_service/internal/products/data/uow/catalog_context.go @@ -1,7 +1,7 @@ package uow import ( - data2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" + data2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" ) type catalogContext struct { diff --git a/internal/services/catalog_write_service/internal/products/data/uow/catalogs_unit_of_work.go b/internal/services/catalog_write_service/internal/products/data/uow/catalogs_unit_of_work.go index 76d8bd2b..3a501434 100644 --- a/internal/services/catalog_write_service/internal/products/data/uow/catalogs_unit_of_work.go +++ b/internal/services/catalog_write_service/internal/products/data/uow/catalogs_unit_of_work.go @@ -9,13 +9,13 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - data2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/repositories" "gorm.io/gorm" ) -type catalogUnitOfWork[TContext data2.CatalogContext] struct { +type catalogUnitOfWork[TContext contracts.CatalogContext] struct { logger logger.Logger db *gorm.DB tracer tracing.AppTracer @@ -25,13 +25,13 @@ func NewCatalogsUnitOfWork( logger logger.Logger, db *gorm.DB, tracer tracing.AppTracer, -) data2.CatalogUnitOfWork { - return &catalogUnitOfWork[data2.CatalogContext]{logger: logger, db: db, tracer: tracer} +) contracts.CatalogUnitOfWork { + return &catalogUnitOfWork[contracts.CatalogContext]{logger: logger, db: db, tracer: tracer} } func (c *catalogUnitOfWork[TContext]) Do( ctx context.Context, - action data2.CatalogUnitOfWorkActionFunc, + action contracts.CatalogUnitOfWorkActionFunc, ) error { // https://gorm.io/docs/transactions.html#Transaction return c.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { diff --git a/internal/services/catalog_write_service/internal/products/dtos/v1/fxparams/product_handler_params.go b/internal/services/catalog_write_service/internal/products/dtos/v1/fxparams/product_handler_params.go new file mode 100644 index 00000000..a3f135f8 --- /dev/null +++ b/internal/services/catalog_write_service/internal/products/dtos/v1/fxparams/product_handler_params.go @@ -0,0 +1,20 @@ +package fxparams + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" + + "go.uber.org/fx" +) + +type ProductHandlerParams struct { + fx.In + + Log logger.Logger + Uow contracts.CatalogUnitOfWork + ProductRepository contracts.ProductRepository + RabbitmqProducer producer.Producer + Tracer tracing.AppTracer +} diff --git a/internal/services/catalog_write_service/internal/products/contracts/params/product_route_params.go b/internal/services/catalog_write_service/internal/products/dtos/v1/fxparams/product_route_params.go similarity index 96% rename from internal/services/catalog_write_service/internal/products/contracts/params/product_route_params.go rename to internal/services/catalog_write_service/internal/products/dtos/v1/fxparams/product_route_params.go index d5b0cc00..f2e8ce06 100644 --- a/internal/services/catalog_write_service/internal/products/contracts/params/product_route_params.go +++ b/internal/services/catalog_write_service/internal/products/dtos/v1/fxparams/product_route_params.go @@ -1,4 +1,4 @@ -package params +package fxparams import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" diff --git a/internal/services/catalog_write_service/internal/products/dto/v1/product_dto.go b/internal/services/catalog_write_service/internal/products/dtos/v1/product_dto.go similarity index 95% rename from internal/services/catalog_write_service/internal/products/dto/v1/product_dto.go rename to internal/services/catalog_write_service/internal/products/dtos/v1/product_dto.go index 70f4e9c9..051c8b42 100644 --- a/internal/services/catalog_write_service/internal/products/dto/v1/product_dto.go +++ b/internal/services/catalog_write_service/internal/products/dtos/v1/product_dto.go @@ -1,4 +1,4 @@ -package dtoV1 +package v1 import ( "time" diff --git a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/commands/create_product_handler.go b/internal/services/catalog_write_service/internal/products/features/creating_product/v1/commands/create_product_handler.go deleted file mode 100644 index 705773fe..00000000 --- a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/commands/create_product_handler.go +++ /dev/null @@ -1,110 +0,0 @@ -package createProductCommand - -import ( - "context" - "fmt" - "net/http" - - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" - dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/dtos" - integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/events/integration_events" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" -) - -type CreateProductHandler struct { - log logger.Logger - uow data.CatalogUnitOfWork - rabbitmqProducer producer.Producer - tracer tracing.AppTracer -} - -func NewCreateProductHandler( - log logger.Logger, - uow data.CatalogUnitOfWork, - rabbitmqProducer producer.Producer, - tracer tracing.AppTracer, -) *CreateProductHandler { - return &CreateProductHandler{ - log: log, - uow: uow, - rabbitmqProducer: rabbitmqProducer, - tracer: tracer, - } -} - -func (c *CreateProductHandler) Handle( - ctx context.Context, - command *CreateProduct, -) (*dtos.CreateProductResponseDto, error) { - product := &models.Product{ - ProductId: command.ProductID, - Name: command.Name, - Description: command.Description, - Price: command.Price, - CreatedAt: command.CreatedAt, - } - - var createProductResult *dtos.CreateProductResponseDto - - err := c.uow.Do(ctx, func(catalogContext data.CatalogContext) error { - createdProduct, err := catalogContext.Products(). - CreateProduct(ctx, product) - if err != nil { - return customErrors.NewApplicationErrorWrapWithCode( - err, - http.StatusConflict, - "product already exists", - ) - } - productDto, err := mapper.Map[*dtoV1.ProductDto](createdProduct) - if err != nil { - return customErrors.NewApplicationErrorWrap( - err, - "error in the mapping ProductDto", - ) - } - - productCreated := integrationEvents.NewProductCreatedV1(productDto) - - err = c.rabbitmqProducer.PublishMessage(ctx, productCreated, nil) - if err != nil { - return customErrors.NewApplicationErrorWrap( - err, - "error in publishing ProductCreated integration_events event", - ) - } - - c.log.Infow( - fmt.Sprintf( - "ProductCreated message with messageId `%s` published to the rabbitmq broker", - productCreated.MessageId, - ), - logger.Fields{"MessageId": productCreated.MessageId}, - ) - - createProductResult = &dtos.CreateProductResponseDto{ - ProductID: product.ProductId, - } - - c.log.Infow( - fmt.Sprintf( - "product with id '%s' created", - command.ProductID, - ), - logger.Fields{ - "ProductId": command.ProductID, - "MessageId": productCreated.MessageId, - }, - ) - - return nil - }) - - return createProductResult, err -} diff --git a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/commands/create_product.go b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product.go similarity index 97% rename from internal/services/catalog_write_service/internal/products/features/creating_product/v1/commands/create_product.go rename to internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product.go index e55d861f..dd0708e9 100644 --- a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/commands/create_product.go +++ b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product.go @@ -1,4 +1,4 @@ -package createProductCommand +package v1 import ( "time" @@ -34,6 +34,7 @@ func NewCreateProduct( if err != nil { return nil, err } + return command, nil } diff --git a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/endpoints/create_product_endpoint.go b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_endpoint.go similarity index 73% rename from internal/services/catalog_write_service/internal/products/features/creating_product/v1/endpoints/create_product_endpoint.go rename to internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_endpoint.go index 9097c2b6..99ebdceb 100644 --- a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/endpoints/create_product_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_endpoint.go @@ -1,13 +1,12 @@ -package endpoints +package v1 import ( "net/http" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/params" - createProductCommand "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/commands" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos" "emperror.dev/errors" "github.com/labstack/echo/v4" @@ -15,10 +14,12 @@ import ( ) type createProductEndpoint struct { - params.ProductRouteParams + fxparams.ProductRouteParams } -func NewCreteProductEndpoint(params params.ProductRouteParams) route.Endpoint { +func NewCreteProductEndpoint( + params fxparams.ProductRouteParams, +) route.Endpoint { return &createProductEndpoint{ProductRouteParams: params} } @@ -49,7 +50,7 @@ func (ep *createProductEndpoint) handler() echo.HandlerFunc { return badRequestErr } - command, err := createProductCommand.NewCreateProduct( + command, err := NewCreateProduct( request.Name, request.Description, request.Price, @@ -63,7 +64,7 @@ func (ep *createProductEndpoint) handler() echo.HandlerFunc { return validationErr } - result, err := mediatr.Send[*createProductCommand.CreateProduct, *dtos.CreateProductResponseDto]( + result, err := mediatr.Send[*CreateProduct, *dtos.CreateProductResponseDto]( ctx, command, ) diff --git a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_handler.go b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_handler.go new file mode 100644 index 00000000..ec317093 --- /dev/null +++ b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_handler.go @@ -0,0 +1,116 @@ +package v1 + +import ( + "context" + "fmt" + "net/http" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" + dtosv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/events/integrationevents" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" + + "github.com/mehdihadeli/go-mediatr" +) + +type createProductHandler struct { + fxparams.ProductHandlerParams +} + +func NewCreateProductHandler( + params fxparams.ProductHandlerParams, +) cqrs.RequestHandlerWithRegisterer[*CreateProduct, *dtos.CreateProductResponseDto] { + return &createProductHandler{ + ProductHandlerParams: params, + } +} + +func (c *createProductHandler) RegisterHandler() error { + return mediatr.RegisterRequestHandler[*CreateProduct, *dtos.CreateProductResponseDto]( + c, + ) +} + +func (c *createProductHandler) Handle( + ctx context.Context, + command *CreateProduct, +) (*dtos.CreateProductResponseDto, error) { + product := &models.Product{ + ProductId: command.ProductID, + Name: command.Name, + Description: command.Description, + Price: command.Price, + CreatedAt: command.CreatedAt, + } + + var createProductResult *dtos.CreateProductResponseDto + + err := c.Uow.Do( + ctx, + func(catalogContext contracts.CatalogContext) error { + createdProduct, err := catalogContext.Products(). + CreateProduct(ctx, product) + if err != nil { + return customErrors.NewApplicationErrorWrapWithCode( + err, + http.StatusConflict, + "product already exists", + ) + } + productDto, err := mapper.Map[*dtosv1.ProductDto]( + createdProduct, + ) + if err != nil { + return customErrors.NewApplicationErrorWrap( + err, + "error in the mapping ProductDto", + ) + } + + productCreated := integrationevents.NewProductCreatedV1( + productDto, + ) + + err = c.RabbitmqProducer.PublishMessage(ctx, productCreated, nil) + if err != nil { + return customErrors.NewApplicationErrorWrap( + err, + "error in publishing ProductCreated integration_events event", + ) + } + + c.Log.Infow( + fmt.Sprintf( + "ProductCreated message with messageId `%s` published to the rabbitmq broker", + productCreated.MessageId, + ), + logger.Fields{"MessageId": productCreated.MessageId}, + ) + + createProductResult = &dtos.CreateProductResponseDto{ + ProductID: product.ProductId, + } + + c.Log.Infow( + fmt.Sprintf( + "product with id '%s' created", + command.ProductID, + ), + logger.Fields{ + "ProductId": command.ProductID, + "MessageId": productCreated.MessageId, + }, + ) + + return nil + }, + ) + + return createProductResult, err +} diff --git a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/dtos/create_product_request_dto.go b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/dtos/create_product_request_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/creating_product/v1/dtos/create_product_request_dto.go rename to internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/dtos/create_product_request_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/dtos/create_product_response_dto.go b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/dtos/create_product_response_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/creating_product/v1/dtos/create_product_response_dto.go rename to internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/dtos/create_product_response_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/events/domain_events/.gitkeep b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/events/domainevents/.gitkeep similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/creating_product/v1/events/domain_events/.gitkeep rename to internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/events/domainevents/.gitkeep diff --git a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/events/integration_events/product_created.go b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/events/integrationevents/product_created.go similarity index 84% rename from internal/services/catalog_write_service/internal/products/features/creating_product/v1/events/integration_events/product_created.go rename to internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/events/integrationevents/product_created.go index c47c2546..da8accf0 100644 --- a/internal/services/catalog_write_service/internal/products/features/creating_product/v1/events/integration_events/product_created.go +++ b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/events/integrationevents/product_created.go @@ -1,8 +1,8 @@ -package integration_events +package integrationevents import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" - dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" + dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" uuid "github.com/satori/go.uuid" ) diff --git a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/commands/delete_product.go b/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product.go similarity index 97% rename from internal/services/catalog_write_service/internal/products/features/deleting_product/v1/commands/delete_product.go rename to internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product.go index 1b125a26..38dd45cf 100644 --- a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/commands/delete_product.go +++ b/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product.go @@ -1,4 +1,4 @@ -package commands +package v1 import ( validation "github.com/go-ozzo/ozzo-validation" diff --git a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/endpoints/delete_product_endpoint.go b/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product_endpoint.go similarity index 79% rename from internal/services/catalog_write_service/internal/products/features/deleting_product/v1/endpoints/delete_product_endpoint.go rename to internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product_endpoint.go index 8de61923..57aa22b2 100644 --- a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/endpoints/delete_product_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product_endpoint.go @@ -1,12 +1,11 @@ -package endpoints +package v1 import ( "net/http" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/params" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1/commands" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1/dtos" "emperror.dev/errors" @@ -15,11 +14,11 @@ import ( ) type deleteProductEndpoint struct { - params.ProductRouteParams + fxparams.ProductRouteParams } func NewDeleteProductEndpoint( - params params.ProductRouteParams, + params fxparams.ProductRouteParams, ) route.Endpoint { return &deleteProductEndpoint{ProductRouteParams: params} } @@ -51,7 +50,7 @@ func (ep *deleteProductEndpoint) handler() echo.HandlerFunc { return badRequestErr } - command, err := commands.NewDeleteProduct(request.ProductID) + command, err := NewDeleteProduct(request.ProductID) if err != nil { validationErr := customErrors.NewValidationErrorWrap( err, @@ -61,7 +60,7 @@ func (ep *deleteProductEndpoint) handler() echo.HandlerFunc { return validationErr } - _, err = mediatr.Send[*commands.DeleteProduct, *mediatr.Unit]( + _, err = mediatr.Send[*DeleteProduct, *mediatr.Unit]( ctx, command, ) diff --git a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/commands/delete_product_handler.go b/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product_handler.go similarity index 62% rename from internal/services/catalog_write_service/internal/products/features/deleting_product/v1/commands/delete_product_handler.go rename to internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product_handler.go index e8a4f350..9fdb1205 100644 --- a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/commands/delete_product_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product_handler.go @@ -1,46 +1,43 @@ -package commands +package v1 import ( "context" "fmt" "net/http" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" - integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1/events/integration_events" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" + integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1/events/integrationevents" "github.com/mehdihadeli/go-mediatr" ) -type DeleteProductHandler struct { - log logger.Logger - uow data.CatalogUnitOfWork - rabbitmqProducer producer.Producer - tracer tracing.AppTracer +type deleteProductHandler struct { + fxparams.ProductHandlerParams } func NewDeleteProductHandler( - log logger.Logger, - uow data.CatalogUnitOfWork, - rabbitmqProducer producer.Producer, - tracer tracing.AppTracer, -) *DeleteProductHandler { - return &DeleteProductHandler{ - log: log, - uow: uow, - rabbitmqProducer: rabbitmqProducer, - tracer: tracer, + params fxparams.ProductHandlerParams, +) cqrs.RequestHandlerWithRegisterer[*DeleteProduct, *mediatr.Unit] { + return &deleteProductHandler{ + ProductHandlerParams: params, } } -func (c *DeleteProductHandler) Handle( +func (c *deleteProductHandler) RegisterHandler() error { + return mediatr.RegisterRequestHandler[*DeleteProduct, *mediatr.Unit]( + c, + ) +} + +func (c *deleteProductHandler) Handle( ctx context.Context, command *DeleteProduct, ) (*mediatr.Unit, error) { - err := c.uow.Do(ctx, func(catalogContext data.CatalogContext) error { + err := c.Uow.Do(ctx, func(catalogContext contracts.CatalogContext) error { if err := catalogContext.Products().DeleteProductByID(ctx, command.ProductID); err != nil { return customErrors.NewApplicationErrorWrapWithCode( err, @@ -52,7 +49,7 @@ func (c *DeleteProductHandler) Handle( productDeleted := integrationEvents.NewProductDeletedV1( command.ProductID.String(), ) - err := c.rabbitmqProducer.PublishMessage(ctx, productDeleted, nil) + err := c.RabbitmqProducer.PublishMessage(ctx, productDeleted, nil) if err != nil { return customErrors.NewApplicationErrorWrap( err, @@ -60,7 +57,7 @@ func (c *DeleteProductHandler) Handle( ) } - c.log.Infow( + c.Log.Infow( fmt.Sprintf( "ProductDeleted message with messageId '%s' published to the rabbitmq broker", productDeleted.MessageId, @@ -68,7 +65,7 @@ func (c *DeleteProductHandler) Handle( logger.Fields{"MessageId": productDeleted.MessageId}, ) - c.log.Infow( + c.Log.Infow( fmt.Sprintf( "product with id '%s' deleted", command.ProductID, diff --git a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/events/integration_events/product_deleted.go b/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/events/integrationevents/product_deleted.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/deleting_product/v1/events/integration_events/product_deleted.go rename to internal/services/catalog_write_service/internal/products/features/deleting_product/v1/events/integrationevents/product_deleted.go diff --git a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/dtos/get_product_by_id_response_dto.go b/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/dtos/get_product_by_id_response_dto.go index 0bace22c..6539a8da 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/dtos/get_product_by_id_response_dto.go +++ b/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/dtos/get_product_by_id_response_dto.go @@ -1,6 +1,6 @@ package dtos -import dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" +import dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" // https://echo.labstack.com/guide/response/ type GetProductByIdResponseDto struct { diff --git a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/queries/get_product_by_id.go b/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id.go similarity index 80% rename from internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/queries/get_product_by_id.go rename to internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id.go index 0dee457c..27884819 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/queries/get_product_by_id.go +++ b/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id.go @@ -1,4 +1,4 @@ -package getProductByIdQuery +package v1 import ( validation "github.com/go-ozzo/ozzo-validation" @@ -24,5 +24,8 @@ func NewGetProductById(productId uuid.UUID) (*GetProductById, error) { } func (p *GetProductById) Validate() error { - return validation.ValidateStruct(p, validation.Field(&p.ProductID, validation.Required, is.UUIDv4)) + return validation.ValidateStruct( + p, + validation.Field(&p.ProductID, validation.Required, is.UUIDv4), + ) } diff --git a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/endpoints/get_product_by_id_endpoint.go b/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id_endpoint.go similarity index 77% rename from internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/endpoints/get_product_by_id_endpoint.go rename to internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id_endpoint.go index bb0e3fa1..a170bb14 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/endpoints/get_product_by_id_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id_endpoint.go @@ -1,13 +1,12 @@ -package endpoints +package v1 import ( "net/http" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/params" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/dtos" - getProductByIdQuery "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/queries" "emperror.dev/errors" "github.com/labstack/echo/v4" @@ -15,11 +14,11 @@ import ( ) type getProductByIdEndpoint struct { - params.ProductRouteParams + fxparams.ProductRouteParams } func NewGetProductByIdEndpoint( - params params.ProductRouteParams, + params fxparams.ProductRouteParams, ) route.Endpoint { return &getProductByIdEndpoint{ProductRouteParams: params} } @@ -51,7 +50,7 @@ func (ep *getProductByIdEndpoint) handler() echo.HandlerFunc { return badRequestErr } - query, err := getProductByIdQuery.NewGetProductById(request.ProductId) + query, err := NewGetProductById(request.ProductId) if err != nil { validationErr := customErrors.NewValidationErrorWrap( err, @@ -61,7 +60,7 @@ func (ep *getProductByIdEndpoint) handler() echo.HandlerFunc { return validationErr } - queryResult, err := mediatr.Send[*getProductByIdQuery.GetProductById, *dtos.GetProductByIdResponseDto]( + queryResult, err := mediatr.Send[*GetProductById, *dtos.GetProductByIdResponseDto]( ctx, query, ) diff --git a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/queries/get_product_by_id_handler.go b/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id_handler.go similarity index 63% rename from internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/queries/get_product_by_id_handler.go rename to internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id_handler.go index a7be089e..c5183b50 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/queries/get_product_by_id_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id_handler.go @@ -1,38 +1,44 @@ -package getProductByIdQuery +package v1 import ( "context" "fmt" "net/http" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" - dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" + dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/dtos" + + "github.com/mehdihadeli/go-mediatr" ) -type GetProductByIdHandler struct { - log logger.Logger - pgRepo data.ProductRepository - tracer tracing.AppTracer +type getProductByIDHandler struct { + fxparams.ProductHandlerParams } -func NewGetProductByIdHandler( - log logger.Logger, - pgRepo data.ProductRepository, - tracer tracing.AppTracer, -) *GetProductByIdHandler { - return &GetProductByIdHandler{log: log, pgRepo: pgRepo, tracer: tracer} +func NewGetProductByIDHandler( + params fxparams.ProductHandlerParams, +) cqrs.RequestHandlerWithRegisterer[*GetProductById, *dtos.GetProductByIdResponseDto] { + return &getProductByIDHandler{ + ProductHandlerParams: params, + } +} + +func (c *getProductByIDHandler) RegisterHandler() error { + return mediatr.RegisterRequestHandler[*GetProductById, *dtos.GetProductByIdResponseDto]( + c, + ) } -func (q *GetProductByIdHandler) Handle( +func (c *getProductByIDHandler) Handle( ctx context.Context, query *GetProductById, ) (*dtos.GetProductByIdResponseDto, error) { - product, err := q.pgRepo.GetProductById(ctx, query.ProductID) + product, err := c.ProductRepository.GetProductById(ctx, query.ProductID) if err != nil { return nil, customErrors.NewApplicationErrorWrapWithCode( err, @@ -52,7 +58,7 @@ func (q *GetProductByIdHandler) Handle( ) } - q.log.Infow( + c.Log.Infow( fmt.Sprintf( "product with id: {%s} fetched", query.ProductID, diff --git a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/dtos/get_products_response_dto.go b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/dtos/get_products_response_dto.go index a28df2e3..d51f19e4 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/dtos/get_products_response_dto.go +++ b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/dtos/get_products_response_dto.go @@ -2,7 +2,7 @@ package dtos import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" + dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" ) // https://echo.labstack.com/guide/response/ diff --git a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/queries/get_products.go b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products.go similarity index 94% rename from internal/services/catalog_write_service/internal/products/features/getting_products/v1/queries/get_products.go rename to internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products.go index 7e8676b0..290150e9 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/queries/get_products.go +++ b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products.go @@ -1,4 +1,4 @@ -package queries +package v1 import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" diff --git a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_endpoint.go similarity index 81% rename from internal/services/catalog_write_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go rename to internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_endpoint.go index 35928fb5..d1f3a701 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_endpoint.go @@ -1,14 +1,13 @@ -package endpoints +package v1 import ( "net/http" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/params" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/dtos" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/queries" "emperror.dev/errors" "github.com/labstack/echo/v4" @@ -16,11 +15,11 @@ import ( ) type getProductsEndpoint struct { - params.ProductRouteParams + fxparams.ProductRouteParams } func NewGetProductsEndpoint( - params params.ProductRouteParams, + params fxparams.ProductRouteParams, ) route.Endpoint { return &getProductsEndpoint{ProductRouteParams: params} } @@ -62,12 +61,12 @@ func (ep *getProductsEndpoint) handler() echo.HandlerFunc { return badRequestErr } - query, err := queries.NewGetProducts(request.ListQuery) + query, err := NewGetProducts(request.ListQuery) if err != nil { return err } - queryResult, err := mediatr.Send[*queries.GetProducts, *dtos.GetProductsResponseDto]( + queryResult, err := mediatr.Send[*GetProducts, *dtos.GetProductsResponseDto]( ctx, query, ) diff --git a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_handler.go b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_handler.go new file mode 100644 index 00000000..286ee5f3 --- /dev/null +++ b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_handler.go @@ -0,0 +1,52 @@ +package v1 + +import ( + "context" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" + dtosv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/dtos" + + "github.com/mehdihadeli/go-mediatr" +) + +type getProductsHandler struct { + fxparams.ProductHandlerParams +} + +func NewGetProductsHandler( + params fxparams.ProductHandlerParams, +) cqrs.RequestHandlerWithRegisterer[*GetProducts, *dtos.GetProductsResponseDto] { + return &getProductsHandler{ + ProductHandlerParams: params, + } +} + +func (c *getProductsHandler) RegisterHandler() error { + return mediatr.RegisterRequestHandler[*GetProducts, *dtos.GetProductsResponseDto]( + c, + ) +} + +func (c *getProductsHandler) Handle( + ctx context.Context, + query *GetProducts, +) (*dtos.GetProductsResponseDto, error) { + products, err := c.ProductRepository.GetAllProducts(ctx, query.ListQuery) + if err != nil { + return nil, err + } + + listResultDto, err := utils.ListResultToListResultDto[*dtosv1.ProductDto]( + products, + ) + if err != nil { + return nil, err + } + + c.Log.Info("products fetched") + + return &dtos.GetProductsResponseDto{Products: listResultDto}, nil +} diff --git a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/queries/get_products_handler.go b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/queries/get_products_handler.go deleted file mode 100644 index d1035d57..00000000 --- a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/queries/get_products_handler.go +++ /dev/null @@ -1,47 +0,0 @@ -package queries - -import ( - "context" - - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" - dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/dtos" -) - -type GetProductsHandler struct { - log logger.Logger - pgRepo data.ProductRepository - tracer tracing.AppTracer -} - -func NewGetProductsHandler( - log logger.Logger, - pgRepo data.ProductRepository, - tracer tracing.AppTracer, -) *GetProductsHandler { - return &GetProductsHandler{log: log, pgRepo: pgRepo, tracer: tracer} -} - -func (c *GetProductsHandler) Handle( - ctx context.Context, - query *GetProducts, -) (*dtos.GetProductsResponseDto, error) { - products, err := c.pgRepo.GetAllProducts(ctx, query.ListQuery) - if err != nil { - return nil, err - } - - listResultDto, err := utils.ListResultToListResultDto[*dto.ProductDto]( - products, - ) - if err != nil { - return nil, err - } - - c.log.Info("products fetched") - - return &dtos.GetProductsResponseDto{Products: listResultDto}, nil -} diff --git a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/dtos/search_products_response_dto.go b/internal/services/catalog_write_service/internal/products/features/searching_product/v1/dtos/search_products_response_dto.go index 6c3e630f..d3ebf020 100644 --- a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/dtos/search_products_response_dto.go +++ b/internal/services/catalog_write_service/internal/products/features/searching_product/v1/dtos/search_products_response_dto.go @@ -2,7 +2,7 @@ package dtos import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" + dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" ) type SearchProductsResponseDto struct { diff --git a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/queries/search_products.go b/internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products.go similarity index 97% rename from internal/services/catalog_write_service/internal/products/features/searching_product/v1/queries/search_products.go rename to internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products.go index 677db550..60a12ac2 100644 --- a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/queries/search_products.go +++ b/internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products.go @@ -1,4 +1,4 @@ -package queries +package v1 import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" diff --git a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/endpoints/search_products_endpoint.go b/internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products_endpoint.go similarity index 82% rename from internal/services/catalog_write_service/internal/products/features/searching_product/v1/endpoints/search_products_endpoint.go rename to internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products_endpoint.go index 0be06f35..1b030304 100644 --- a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/endpoints/search_products_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products_endpoint.go @@ -1,14 +1,13 @@ -package endpoints +package v1 import ( "net/http" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/params" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searching_product/v1/dtos" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searching_product/v1/queries" "emperror.dev/errors" "github.com/labstack/echo/v4" @@ -16,11 +15,11 @@ import ( ) type searchProductsEndpoint struct { - params.ProductRouteParams + fxparams.ProductRouteParams } func NewSearchProductsEndpoint( - params params.ProductRouteParams, + params fxparams.ProductRouteParams, ) route.Endpoint { return &searchProductsEndpoint{ProductRouteParams: params} } @@ -62,7 +61,7 @@ func (ep *searchProductsEndpoint) handler() echo.HandlerFunc { return badRequestErr } - query, err := queries.NewSearchProducts( + query, err := NewSearchProducts( request.SearchText, request.ListQuery, ) @@ -75,7 +74,7 @@ func (ep *searchProductsEndpoint) handler() echo.HandlerFunc { return validationErr } - queryResult, err := mediatr.Send[*queries.SearchProducts, *dtos.SearchProductsResponseDto]( + queryResult, err := mediatr.Send[*SearchProducts, *dtos.SearchProductsResponseDto]( ctx, query, ) diff --git a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/queries/search_products_handler.go b/internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products_handler.go similarity index 61% rename from internal/services/catalog_write_service/internal/products/features/searching_product/v1/queries/search_products_handler.go rename to internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products_handler.go index 62f75485..8f344a8d 100644 --- a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/queries/search_products_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products_handler.go @@ -1,36 +1,41 @@ -package queries +package v1 import ( "context" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" - dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" + dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searching_product/v1/dtos" + + "github.com/mehdihadeli/go-mediatr" ) -type SearchProductsHandler struct { - log logger.Logger - pgRepo data.ProductRepository - tracer tracing.AppTracer +type searchProductsHandler struct { + fxparams.ProductHandlerParams } func NewSearchProductsHandler( - log logger.Logger, - pgRepo data.ProductRepository, - tracer tracing.AppTracer, -) *SearchProductsHandler { - return &SearchProductsHandler{log: log, pgRepo: pgRepo, tracer: tracer} + params fxparams.ProductHandlerParams, +) cqrs.RequestHandlerWithRegisterer[*SearchProducts, *dtos.SearchProductsResponseDto] { + return &searchProductsHandler{ + ProductHandlerParams: params, + } +} + +func (c *searchProductsHandler) RegisterHandler() error { + return mediatr.RegisterRequestHandler[*SearchProducts, *dtos.SearchProductsResponseDto]( + c, + ) } -func (c *SearchProductsHandler) Handle( +func (c *searchProductsHandler) Handle( ctx context.Context, query *SearchProducts, ) (*dtos.SearchProductsResponseDto, error) { - products, err := c.pgRepo.SearchProducts( + products, err := c.ProductRepository.SearchProducts( ctx, query.SearchText, query.ListQuery, @@ -52,7 +57,7 @@ func (c *SearchProductsHandler) Handle( ) } - c.log.Info("products fetched") + c.Log.Info("products fetched") return &dtos.SearchProductsResponseDto{Products: listResultDto}, nil } diff --git a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/events/integration_events/product_updated.go b/internal/services/catalog_write_service/internal/products/features/updating_product/v1/events/integrationevents/product_updated.go similarity index 84% rename from internal/services/catalog_write_service/internal/products/features/updating_product/v1/events/integration_events/product_updated.go rename to internal/services/catalog_write_service/internal/products/features/updating_product/v1/events/integrationevents/product_updated.go index ae0c190e..2abfb056 100644 --- a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/events/integration_events/product_updated.go +++ b/internal/services/catalog_write_service/internal/products/features/updating_product/v1/events/integrationevents/product_updated.go @@ -1,8 +1,8 @@ -package integration_events +package integrationevents import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" - dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" + dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" uuid "github.com/satori/go.uuid" ) diff --git a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/commands/update_product.go b/internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product.go similarity index 98% rename from internal/services/catalog_write_service/internal/products/features/updating_product/v1/commands/update_product.go rename to internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product.go index 6900a236..067bc457 100644 --- a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/commands/update_product.go +++ b/internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product.go @@ -1,4 +1,4 @@ -package commands +package v1 import ( "time" diff --git a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/endpoints/update_product_endpoint.go b/internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product_endpoint.go similarity index 81% rename from internal/services/catalog_write_service/internal/products/features/updating_product/v1/endpoints/update_product_endpoint.go rename to internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product_endpoint.go index 74d1fe36..57020da4 100644 --- a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/endpoints/update_product_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product_endpoint.go @@ -1,12 +1,11 @@ -package endpoints +package v1 import ( "net/http" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/params" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/commands" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/dtos" "emperror.dev/errors" @@ -15,11 +14,11 @@ import ( ) type updateProductEndpoint struct { - params.ProductRouteParams + fxparams.ProductRouteParams } func NewUpdateProductEndpoint( - params params.ProductRouteParams, + params fxparams.ProductRouteParams, ) route.Endpoint { return &updateProductEndpoint{ProductRouteParams: params} } @@ -52,7 +51,7 @@ func (ep *updateProductEndpoint) handler() echo.HandlerFunc { return badRequestErr } - command, err := commands.NewUpdateProduct( + command, err := NewUpdateProduct( request.ProductID, request.Name, request.Description, @@ -67,7 +66,7 @@ func (ep *updateProductEndpoint) handler() echo.HandlerFunc { return validationErr } - _, err = mediatr.Send[*commands.UpdateProduct, *mediatr.Unit]( + _, err = mediatr.Send[*UpdateProduct, *mediatr.Unit]( ctx, command, ) diff --git a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/commands/update_product_handler.go b/internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product_handler.go similarity index 67% rename from internal/services/catalog_write_service/internal/products/features/updating_product/v1/commands/update_product_handler.go rename to internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product_handler.go index f4971ef2..a67462a7 100644 --- a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/commands/update_product_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product_handler.go @@ -1,48 +1,46 @@ -package commands +package v1 import ( "context" "fmt" "net/http" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" - dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/events/integration_events" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" + dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/events/integrationevents" "github.com/mehdihadeli/go-mediatr" ) -type UpdateProductHandler struct { - log logger.Logger - uow data.CatalogUnitOfWork - rabbitmqProducer producer.Producer - tracer tracing.AppTracer +type updateProductHandler struct { + fxparams.ProductHandlerParams + cqrs.HandlerRegisterer } func NewUpdateProductHandler( - log logger.Logger, - uow data.CatalogUnitOfWork, - rabbitmqProducer producer.Producer, - tracer tracing.AppTracer, -) *UpdateProductHandler { - return &UpdateProductHandler{ - log: log, - uow: uow, - rabbitmqProducer: rabbitmqProducer, - tracer: tracer, + params fxparams.ProductHandlerParams, +) cqrs.RequestHandlerWithRegisterer[*UpdateProduct, *mediatr.Unit] { + return &updateProductHandler{ + ProductHandlerParams: params, } } -func (c *UpdateProductHandler) Handle( +func (c *updateProductHandler) RegisterHandler() error { + return mediatr.RegisterRequestHandler[*UpdateProduct, *mediatr.Unit]( + c, + ) +} + +func (c *updateProductHandler) Handle( ctx context.Context, command *UpdateProduct, ) (*mediatr.Unit, error) { - err := c.uow.Do(ctx, func(catalogContext data.CatalogContext) error { + err := c.Uow.Do(ctx, func(catalogContext contracts.CatalogContext) error { product, err := catalogContext.Products(). GetProductById(ctx, command.ProductID) if err != nil { @@ -78,9 +76,9 @@ func (c *UpdateProductHandler) Handle( ) } - productUpdated := integration_events.NewProductUpdatedV1(productDto) + productUpdated := integrationevents.NewProductUpdatedV1(productDto) - err = c.rabbitmqProducer.PublishMessage(ctx, productUpdated, nil) + err = c.RabbitmqProducer.PublishMessage(ctx, productUpdated, nil) if err != nil { return customErrors.NewApplicationErrorWrap( err, @@ -88,7 +86,7 @@ func (c *UpdateProductHandler) Handle( ) } - c.log.Infow( + c.Log.Infow( fmt.Sprintf( "product with id '%s' updated", command.ProductID, @@ -96,7 +94,7 @@ func (c *UpdateProductHandler) Handle( logger.Fields{"ProductId": command.ProductID}, ) - c.log.Infow( + c.Log.Infow( fmt.Sprintf( "ProductUpdated message with messageId `%s` published to the rabbitmq broker", productUpdated.MessageId, diff --git a/internal/services/catalog_write_service/internal/products/products_fx.go b/internal/services/catalog_write_service/internal/products/products_fx.go index cdb6b053..25afd4d9 100644 --- a/internal/services/catalog_write_service/internal/products/products_fx.go +++ b/internal/services/catalog_write_service/internal/products/products_fx.go @@ -1,15 +1,16 @@ package products import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/repositories" - createProductV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/endpoints" - deleteProductV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1/endpoints" - getProductByIdV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/endpoints" - getProductsV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/endpoints" - searchProductsV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searching_product/v1/endpoints" - updateProductsV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/endpoints" + creatingproductv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1" + deletingproductv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1" + gettingproductbyidv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1" + gettingproductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1" + searchingproductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searching_product/v1" + updatingoroductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/grpc" "github.com/labstack/echo/v4" @@ -36,26 +37,58 @@ var Module = fx.Module( }, fx.ResultTags(`name:"product-echo-group"`)), ), + // add cqrs handlers to DI fx.Provide( + cqrs.AsHandler( + creatingproductv1.NewCreateProductHandler, + "product-handlers", + ), + cqrs.AsHandler( + gettingproductsv1.NewGetProductsHandler, + "product-handlers", + ), + cqrs.AsHandler( + deletingproductv1.NewDeleteProductHandler, + "product-handlers", + ), + cqrs.AsHandler( + gettingproductbyidv1.NewGetProductByIDHandler, + "product-handlers", + ), + cqrs.AsHandler( + searchingproductsv1.NewSearchProductsHandler, + "product-handlers", + ), + cqrs.AsHandler( + updatingoroductsv1.NewUpdateProductHandler, + "product-handlers", + ), + ), + + // add endpoints to DI + fx.Provide( + route.AsRoute( + creatingproductv1.NewCreteProductEndpoint, + "product-routes", + ), route.AsRoute( - createProductV1.NewCreteProductEndpoint, + updatingoroductsv1.NewUpdateProductEndpoint, "product-routes", ), route.AsRoute( - updateProductsV1.NewUpdateProductEndpoint, + gettingproductsv1.NewGetProductsEndpoint, "product-routes", ), - route.AsRoute(getProductsV1.NewGetProductsEndpoint, "product-routes"), route.AsRoute( - searchProductsV1.NewSearchProductsEndpoint, + searchingproductsv1.NewSearchProductsEndpoint, "product-routes", ), route.AsRoute( - getProductByIdV1.NewGetProductByIdEndpoint, + gettingproductbyidv1.NewGetProductByIdEndpoint, "product-routes", ), route.AsRoute( - deleteProductV1.NewDeleteProductEndpoint, + deletingproductv1.NewDeleteProductEndpoint, "product-routes", ), ), diff --git a/internal/services/catalog_write_service/internal/shared/app/app.go b/internal/services/catalog_write_service/internal/shared/app/app.go index 77492e8c..08756295 100644 --- a/internal/services/catalog_write_service/internal/shared/app/app.go +++ b/internal/services/catalog_write_service/internal/shared/app/app.go @@ -21,9 +21,15 @@ func (a *App) Run() { app := appBuilder.Build() // configure application - app.ConfigureCatalogs() - - app.MapCatalogsEndpoints() + err := app.ConfigureCatalogs() + if err != nil { + app.Logger().Fatalf("Error in ConfigureCatalogs", err) + } + + err = app.MapCatalogsEndpoints() + if err != nil { + app.Logger().Fatalf("Error in MapCatalogsEndpoints", err) + } app.Logger().Info("Starting catalog_service application") app.ResolveFunc(func(tracer tracing.AppTracer) { diff --git a/internal/services/catalog_write_service/internal/shared/app/application.go b/internal/services/catalog_write_service/internal/shared/app/application.go index a74de8cc..cf8842d4 100644 --- a/internal/services/catalog_write_service/internal/shared/app/application.go +++ b/internal/services/catalog_write_service/internal/shared/app/application.go @@ -1,7 +1,7 @@ package app import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/configurations/catalogs" @@ -18,7 +18,7 @@ func NewCatalogsWriteApplication( decorates []interface{}, options []fx.Option, logger logger.Logger, - environment environemnt.Environment, + environment environment.Environment, ) *CatalogsWriteApplication { app := fxapp.NewApplication(providers, decorates, options, logger, environment) return &CatalogsWriteApplication{ diff --git a/internal/services/catalog_write_service/internal/shared/app/test/test_app.go b/internal/services/catalog_write_service/internal/shared/app/test/test_app.go index 03cd6566..340cdffa 100644 --- a/internal/services/catalog_write_service/internal/shared/app/test/test_app.go +++ b/internal/services/catalog_write_service/internal/shared/app/test/test_app.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" + fxcontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc" config3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/config" @@ -17,7 +17,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/testcontainer/gorm" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/testcontainer/rabbitmq" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" + productcontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/configurations/catalogs" productsService "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/grpc/genproto" @@ -30,13 +30,13 @@ type TestApp struct{} type TestAppResult struct { Cfg *config.AppOptions Bus bus.RabbitmqBus - Container contracts.Container + Container fxcontracts.Container Logger logger.Logger RabbitmqOptions *config2.RabbitmqOptions EchoHttpOptions *config3.EchoHttpOptions GormOptions *gormPostgres.GormOptions - CatalogUnitOfWorks data.CatalogUnitOfWork - ProductRepository data.ProductRepository + CatalogUnitOfWorks productcontracts.CatalogUnitOfWork + ProductRepository productcontracts.ProductRepository Gorm *gorm2.DB ProductServiceClient productsService.ProductsServiceClient GrpcClient grpc.GrpcClient @@ -61,9 +61,15 @@ func (a *TestApp) Run(t *testing.T) (result *TestAppResult) { testApp := appBuilder.Build() - testApp.ConfigureCatalogs() + err := testApp.ConfigureCatalogs() + if err != nil { + testApp.Logger().Fatalf("Error in ConfigureCatalogs", err) + } - testApp.MapCatalogsEndpoints() + err = testApp.MapCatalogsEndpoints() + if err != nil { + testApp.Logger().Fatalf("Error in MapCatalogsEndpoints", err) + } testApp.ResolveFunc( func(cfg *config.AppOptions, @@ -71,8 +77,8 @@ func (a *TestApp) Run(t *testing.T) (result *TestAppResult) { logger logger.Logger, rabbitmqOptions *config2.RabbitmqOptions, gormOptions *gormPostgres.GormOptions, - catalogUnitOfWorks data.CatalogUnitOfWork, - productRepository data.ProductRepository, + catalogUnitOfWorks productcontracts.CatalogUnitOfWork, + productRepository productcontracts.ProductRepository, gorm *gorm2.DB, echoOptions *config3.EchoHttpOptions, grpcClient grpc.GrpcClient, @@ -105,7 +111,8 @@ func (a *TestApp) Run(t *testing.T) (result *TestAppResult) { // short timeout for handling start hooks and setup dependencies startCtx, cancel := context.WithTimeout(context.Background(), duration) defer cancel() - err := testApp.Start(startCtx) + + err = testApp.Start(startCtx) if err != nil { t.Errorf("Error starting, err: %v", err) os.Exit(1) diff --git a/internal/services/catalog_write_service/internal/shared/app/test/test_application.go b/internal/services/catalog_write_service/internal/shared/app/test/test_application.go index e3bf2450..929735e1 100644 --- a/internal/services/catalog_write_service/internal/shared/app/test/test_application.go +++ b/internal/services/catalog_write_service/internal/shared/app/test/test_application.go @@ -1,7 +1,7 @@ package test import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/test" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/app" @@ -22,7 +22,7 @@ func NewCatalogsWriteTestApplication( decorates []interface{}, options []fx.Option, logger logger.Logger, - environment environemnt.Environment, + environment environment.Environment, ) *CatalogsWriteTestApplication { testApp := test.NewTestApplication( tb, diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator.go b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator.go index 94d03293..fb96406e 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator.go +++ b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator.go @@ -36,7 +36,7 @@ func NewCatalogsServiceConfigurator( } } -func (ic *CatalogsServiceConfigurator) ConfigureCatalogs() { +func (ic *CatalogsServiceConfigurator) ConfigureCatalogs() error { // Shared // Infrastructure ic.infrastructureConfigurator.ConfigInfrastructures() @@ -56,10 +56,12 @@ func (ic *CatalogsServiceConfigurator) ConfigureCatalogs() { // Modules // Product module - ic.productsModuleConfigurator.ConfigureProductsModule() + err := ic.productsModuleConfigurator.ConfigureProductsModule() + + return err } -func (ic *CatalogsServiceConfigurator) MapCatalogsEndpoints() { +func (ic *CatalogsServiceConfigurator) MapCatalogsEndpoints() error { // Shared ic.ResolveFunc( func(catalogsServer echocontracts.EchoHttpServer, options *config.AppOptions) error { @@ -88,5 +90,7 @@ func (ic *CatalogsServiceConfigurator) MapCatalogsEndpoints() { // Modules // Products CatalogsServiceModule endpoints - ic.productsModuleConfigurator.MapProductsEndpoints() + err := ic.productsModuleConfigurator.MapProductsEndpoints() + + return err } diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_fx.go b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_fx.go index 660bd220..47f89d94 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_fx.go +++ b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_fx.go @@ -63,8 +63,13 @@ func provideCatalogsMetrics( } getProductByIdGrpcRequests, err := meter.Float64Counter( - fmt.Sprintf("%s_get_product_by_id_grpc_requests_total", cfg.ServiceName), - api.WithDescription("The total number of get product by id grpc requests"), + fmt.Sprintf( + "%s_get_product_by_id_grpc_requests_total", + cfg.ServiceName, + ), + api.WithDescription( + "The total number of get product by id grpc requests", + ), ) if err != nil { return nil, err @@ -79,88 +84,65 @@ func provideCatalogsMetrics( } createProductRabbitMQMessages, err := meter.Float64Counter( - fmt.Sprintf("%s_create_product_rabbitmq_messages_total", cfg.ServiceName), - api.WithDescription("The total number of create product rabbirmq messages"), + fmt.Sprintf( + "%s_create_product_rabbitmq_messages_total", + cfg.ServiceName, + ), + api.WithDescription( + "The total number of create product rabbirmq messages", + ), ) if err != nil { return nil, err } updateProductRabbitMQMessages, err := meter.Float64Counter( - fmt.Sprintf("%s_update_product_rabbitmq_messages_total", cfg.ServiceName), - api.WithDescription("The total number of update product rabbirmq messages"), + fmt.Sprintf( + "%s_update_product_rabbitmq_messages_total", + cfg.ServiceName, + ), + api.WithDescription( + "The total number of update product rabbirmq messages", + ), ) if err != nil { return nil, err } deleteProductRabbitMQMessages, err := meter.Float64Counter( - fmt.Sprintf("%s_delete_product_rabbitmq_messages_total", cfg.ServiceName), - api.WithDescription("The total number of delete product rabbirmq messages"), + fmt.Sprintf( + "%s_delete_product_rabbitmq_messages_total", + cfg.ServiceName, + ), + api.WithDescription( + "The total number of delete product rabbirmq messages", + ), ) if err != nil { return nil, err } successRabbitMQMessages, err := meter.Float64Counter( - fmt.Sprintf("%s_search_product_rabbitmq_messages_total", cfg.ServiceName), - api.WithDescription("The total number of success rabbitmq processed messages"), + fmt.Sprintf( + "%s_search_product_rabbitmq_messages_total", + cfg.ServiceName, + ), + api.WithDescription( + "The total number of success rabbitmq processed messages", + ), ) if err != nil { return nil, err } errorRabbitMQMessages, err := meter.Float64Counter( - fmt.Sprintf("%s_error_rabbitmq_processed_messages_total", cfg.ServiceName), - api.WithDescription("The total number of error rabbitmq processed messages"), - ) - if err != nil { - return nil, err - } - - createProductHttpRequests, err := meter.Float64Counter( - fmt.Sprintf("%s_create_product_http_requests_total", cfg.ServiceName), - api.WithDescription("The total number of create product http requests"), - ) - if err != nil { - return nil, err - } - - updateProductHttpRequests, err := meter.Float64Counter( - fmt.Sprintf("%s_update_product_http_requests_total", cfg.ServiceName), - api.WithDescription("The total number of update product http requests"), - ) - if err != nil { - return nil, err - } - - deleteProductHttpRequests, err := meter.Float64Counter( - fmt.Sprintf("%s_delete_product_http_requests_total", cfg.ServiceName), - api.WithDescription("The total number of delete product http requests"), - ) - if err != nil { - return nil, err - } - - getProductByIdHttpRequests, err := meter.Float64Counter( - fmt.Sprintf("%s_get_product_by_id_http_requests_total", cfg.ServiceName), - api.WithDescription("The total number of get product by id http requests"), - ) - if err != nil { - return nil, err - } - - getProductsHttpRequests, err := meter.Float64Counter( - fmt.Sprintf("%s_get_products_http_requests_total", cfg.ServiceName), - api.WithDescription("The total number of get products http requests"), - ) - if err != nil { - return nil, err - } - - searchProductHttpRequests, err := meter.Float64Counter( - fmt.Sprintf("%s_search_product_http_requests_total", cfg.ServiceName), - api.WithDescription("The total number of search product http requests"), + fmt.Sprintf( + "%s_error_rabbitmq_processed_messages_total", + cfg.ServiceName, + ), + api.WithDescription( + "The total number of error rabbitmq processed messages", + ), ) if err != nil { return nil, err @@ -170,18 +152,12 @@ func provideCatalogsMetrics( CreateProductRabbitMQMessages: createProductRabbitMQMessages, GetProductByIdGrpcRequests: getProductByIdGrpcRequests, CreateProductGrpcRequests: createProductGrpcRequests, - CreateProductHttpRequests: createProductHttpRequests, DeleteProductRabbitMQMessages: deleteProductRabbitMQMessages, DeleteProductGrpcRequests: deleteProductGrpcRequests, - DeleteProductHttpRequests: deleteProductHttpRequests, ErrorRabbitMQMessages: errorRabbitMQMessages, - GetProductByIdHttpRequests: getProductByIdHttpRequests, - GetProductsHttpRequests: getProductsHttpRequests, SearchProductGrpcRequests: searchProductGrpcRequests, - SearchProductHttpRequests: searchProductHttpRequests, SuccessRabbitMQMessages: successRabbitMQMessages, UpdateProductRabbitMQMessages: updateProductRabbitMQMessages, UpdateProductGrpcRequests: updateProductGrpcRequests, - UpdateProductHttpRequests: updateProductHttpRequests, }, nil } diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go index f4022183..41668319 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go +++ b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go @@ -5,9 +5,9 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/pipelines" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" - pipelines2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/pipelines" + pipelines2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/mediatr/pipelines" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - tracingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/pipelines" + tracingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/mediatr/pipelines" "github.com/mehdihadeli/go-mediatr" ) @@ -29,11 +29,11 @@ func (ic *InfrastructureConfigurator) ConfigInfrastructures() { func(logger logger.Logger, tracer tracing.AppTracer, metrics metrics.AppMetrics) error { err := mediatr.RegisterRequestPipelineBehaviors( pipelines.NewLoggingPipeline(logger), - tracingpipelines.NewTracingPipeline( + tracingpipelines.NewMediatorTracingPipeline( tracer, tracingpipelines.WithLogger(logger), ), - pipelines2.NewMetricsPipeline( + pipelines2.NewMediatorMetricsPipeline( metrics, pipelines2.WithLogger(logger), ), diff --git a/internal/services/catalog_write_service/internal/shared/grpc/product_grpc_service_server.go b/internal/services/catalog_write_service/internal/shared/grpc/product_grpc_service_server.go index 9c7d2500..b4f96829 100644 --- a/internal/services/catalog_write_service/internal/shared/grpc/product_grpc_service_server.go +++ b/internal/services/catalog_write_service/internal/shared/grpc/product_grpc_service_server.go @@ -8,11 +8,11 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" - createProductCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/commands" - createProductDtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/dtos" + createProductCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1" + createProductDtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos" + getProductByIdQueryV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1" getProductByIdDtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/dtos" - getProductByIdQueryV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/queries" - updateProductCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/commands" + updateProductCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/contracts" productsService "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/grpc/genproto" @@ -39,7 +39,10 @@ func NewProductGrpcService( catalogsMetrics *contracts.CatalogsMetrics, logger logger.Logger, ) *ProductGrpcServiceServer { - return &ProductGrpcServiceServer{catalogsMetrics: catalogsMetrics, logger: logger} + return &ProductGrpcServiceServer{ + catalogsMetrics: catalogsMetrics, + logger: logger, + } } func (s *ProductGrpcServiceServer) CreateProduct( @@ -89,7 +92,9 @@ func (s *ProductGrpcServiceServer) CreateProduct( return nil, err } - return &productsService.CreateProductRes{ProductId: result.ProductID.String()}, nil + return &productsService.CreateProductRes{ + ProductId: result.ProductID.String(), + }, nil } func (s *ProductGrpcServiceServer) UpdateProduct( diff --git a/internal/services/catalog_write_service/internal/shared/test_fixtures/integration/integration_test_fixture.go b/internal/services/catalog_write_service/internal/shared/test_fixtures/integration/integration_test_fixture.go index d777f788..94b5526e 100644 --- a/internal/services/catalog_write_service/internal/shared/test_fixtures/integration/integration_test_fixture.go +++ b/internal/services/catalog_write_service/internal/shared/test_fixtures/integration/integration_test_fixture.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" + fxcontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/bus" @@ -13,7 +13,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/testfixture" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" + productscontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/app/test" productsService "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/grpc/genproto" @@ -32,9 +32,9 @@ type IntegrationTestSharedFixture struct { Cfg *config.AppOptions Log logger.Logger Bus bus.Bus - CatalogUnitOfWorks data.CatalogUnitOfWork - ProductRepository data.ProductRepository - Container contracts.Container + CatalogUnitOfWorks productscontracts.CatalogUnitOfWork + ProductRepository productscontracts.ProductRepository + Container fxcontracts.Container DbCleaner dbcleaner.DbCleaner RabbitmqCleaner *rabbithole.Client rabbitmqOptions *config2.RabbitmqOptions diff --git a/internal/services/catalog_write_service/internal/shared/test_fixtures/unit_test/unit_test_fixture.go b/internal/services/catalog_write_service/internal/shared/test_fixtures/unit_test/unit_test_fixture.go index a74f5776..4d2492f6 100644 --- a/internal/services/catalog_write_service/internal/shared/test_fixtures/unit_test/unit_test_fixture.go +++ b/internal/services/catalog_write_service/internal/shared/test_fixtures/unit_test/unit_test_fixture.go @@ -9,8 +9,8 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" mocks3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/mocks" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" - dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" + dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/mocks/testData" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/mocks" @@ -90,7 +90,7 @@ func (c *UnitTestSharedFixture) SetupTest() { var mockUOW *mock.Call mockUOW = uow.On("Do", mock.Anything, mock.Anything). Run(func(args mock.Arguments) { - fn, ok := args.Get(1).(data.CatalogUnitOfWorkActionFunc) + fn, ok := args.Get(1).(contracts.CatalogUnitOfWorkActionFunc) if !ok { panic("argument mismatch") } diff --git a/internal/services/catalog_write_service/mocks/CatalogContext.go b/internal/services/catalog_write_service/mocks/CatalogContext.go index 4d0c1ce0..7aa905db 100644 --- a/internal/services/catalog_write_service/mocks/CatalogContext.go +++ b/internal/services/catalog_write_service/mocks/CatalogContext.go @@ -3,7 +3,8 @@ package mocks import ( - data "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" + data "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" + mock "github.com/stretchr/testify/mock" ) diff --git a/internal/services/catalog_write_service/mocks/CatalogUnitOfWork.go b/internal/services/catalog_write_service/mocks/CatalogUnitOfWork.go index 886dfa9f..b7964161 100644 --- a/internal/services/catalog_write_service/mocks/CatalogUnitOfWork.go +++ b/internal/services/catalog_write_service/mocks/CatalogUnitOfWork.go @@ -5,7 +5,8 @@ package mocks import ( context "context" - data "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" + data "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" + mock "github.com/stretchr/testify/mock" ) diff --git a/internal/services/catalog_write_service/mocks/CatalogUnitOfWorkActionFunc.go b/internal/services/catalog_write_service/mocks/CatalogUnitOfWorkActionFunc.go index dea44acd..8e1fccec 100644 --- a/internal/services/catalog_write_service/mocks/CatalogUnitOfWorkActionFunc.go +++ b/internal/services/catalog_write_service/mocks/CatalogUnitOfWorkActionFunc.go @@ -3,7 +3,8 @@ package mocks import ( - data "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" + data "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" + mock "github.com/stretchr/testify/mock" ) diff --git a/internal/services/catalog_write_service/mocks/ProductRepository.go b/internal/services/catalog_write_service/mocks/ProductRepository.go index e67c2b85..ff299e33 100644 --- a/internal/services/catalog_write_service/mocks/ProductRepository.go +++ b/internal/services/catalog_write_service/mocks/ProductRepository.go @@ -5,13 +5,11 @@ package mocks import ( context "context" - mock "github.com/stretchr/testify/mock" - - models "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" - utils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" + models "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" uuid "github.com/satori/go.uuid" + mock "github.com/stretchr/testify/mock" ) // ProductRepository is an autogenerated mock type for the ProductRepository type diff --git a/internal/services/catalog_write_service/test/end_to_end/products/features/creating_product/v1/create_product_test.go b/internal/services/catalog_write_service/test/end_to_end/products/features/creating_product/v1/create_product_test.go index 530611e3..e37207fb 100644 --- a/internal/services/catalog_write_service/test/end_to_end/products/features/creating_product/v1/create_product_test.go +++ b/internal/services/catalog_write_service/test/end_to_end/products/features/creating_product/v1/create_product_test.go @@ -8,7 +8,7 @@ import ( "net/http" "testing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" "github.com/brianvoe/gofakeit/v6" diff --git a/internal/services/catalog_write_service/test/integration/products/data/uow/catalogs_unit_of_work_integration_test.go b/internal/services/catalog_write_service/test/integration/products/data/uow/catalogs_unit_of_work_integration_test.go index 89769b07..cac04ee5 100644 --- a/internal/services/catalog_write_service/test/integration/products/data/uow/catalogs_unit_of_work_integration_test.go +++ b/internal/services/catalog_write_service/test/integration/products/data/uow/catalogs_unit_of_work_integration_test.go @@ -9,7 +9,7 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - data2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts/data" + data2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" diff --git a/internal/services/catalog_write_service/test/integration/products/features/creating_product/v1/create_product_test.go b/internal/services/catalog_write_service/test/integration/products/features/creating_product/v1/create_product_test.go index f9ef809d..d68e0bcc 100644 --- a/internal/services/catalog_write_service/test/integration/products/features/creating_product/v1/create_product_test.go +++ b/internal/services/catalog_write_service/test/integration/products/features/creating_product/v1/create_product_test.go @@ -12,9 +12,9 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/hypothesis" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging" - createProductCommand "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/commands" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/dtos" - integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/events/integration_events" + createProductCommand "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos" + integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/events/integrationevents" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" diff --git a/internal/services/catalog_write_service/test/integration/products/features/deleting_product/v1/delete_product_test.go b/internal/services/catalog_write_service/test/integration/products/features/deleting_product/v1/delete_product_test.go index db6ba166..fbebfc0c 100644 --- a/internal/services/catalog_write_service/test/integration/products/features/deleting_product/v1/delete_product_test.go +++ b/internal/services/catalog_write_service/test/integration/products/features/deleting_product/v1/delete_product_test.go @@ -12,8 +12,8 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/hypothesis" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1/commands" - integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1/events/integration_events" + v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1" + integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1/events/integrationevents" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" "github.com/mehdihadeli/go-mediatr" @@ -37,7 +37,7 @@ var _ = Describe("Delete Product Feature", func() { var ( ctx context.Context err error - command *commands.DeleteProduct + command *v1.DeleteProduct result *mediatr.Unit id uuid.UUID notExistsId uuid.UUID @@ -83,13 +83,13 @@ var _ = Describe("Delete Product Feature", func() { integrationFixture.Bus, nil, ) - command, err = commands.NewDeleteProduct(id) + command, err = v1.NewDeleteProduct(id) Expect(err).ShouldNot(HaveOccurred()) }) When("the DeleteProduct command is executed for existing product", func() { BeforeEach(func() { - result, err = mediatr.Send[*commands.DeleteProduct, *mediatr.Unit]( + result, err = mediatr.Send[*v1.DeleteProduct, *mediatr.Unit]( ctx, command, ) @@ -114,13 +114,13 @@ var _ = Describe("Delete Product Feature", func() { Context("Given product does not exists in the system", func() { BeforeEach(func() { notExistsId = uuid.NewV4() - command, err = commands.NewDeleteProduct(notExistsId) + command, err = v1.NewDeleteProduct(notExistsId) Expect(err).ShouldNot(HaveOccurred()) }) When("the DeleteProduct command is executed for non-existing product", func() { BeforeEach(func() { - result, err = mediatr.Send[*commands.DeleteProduct, *mediatr.Unit]( + result, err = mediatr.Send[*v1.DeleteProduct, *mediatr.Unit]( ctx, command, ) @@ -154,13 +154,13 @@ var _ = Describe("Delete Product Feature", func() { integrationFixture.Bus, nil, ) - command, err = commands.NewDeleteProduct(id) + command, err = v1.NewDeleteProduct(id) Expect(err).ShouldNot(HaveOccurred()) }) When("the DeleteProduct command is executed for existing product", func() { BeforeEach(func() { - result, err = mediatr.Send[*commands.DeleteProduct, *mediatr.Unit]( + result, err = mediatr.Send[*v1.DeleteProduct, *mediatr.Unit]( ctx, command, ) diff --git a/internal/services/catalog_write_service/test/integration/products/features/getting_product_by_id/v1/get_product_by_id_test.go b/internal/services/catalog_write_service/test/integration/products/features/getting_product_by_id/v1/get_product_by_id_test.go index 15836714..cad38852 100644 --- a/internal/services/catalog_write_service/test/integration/products/features/getting_product_by_id/v1/get_product_by_id_test.go +++ b/internal/services/catalog_write_service/test/integration/products/features/getting_product_by_id/v1/get_product_by_id_test.go @@ -10,8 +10,8 @@ import ( "time" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + getProductByIdQuery "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/dtos" - getProductByIdQuery "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/queries" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" "github.com/mehdihadeli/go-mediatr" diff --git a/internal/services/catalog_write_service/test/integration/products/features/getting_products/v1/get_products_test.go b/internal/services/catalog_write_service/test/integration/products/features/getting_products/v1/get_products_test.go index 64ce9eda..9eff22de 100644 --- a/internal/services/catalog_write_service/test/integration/products/features/getting_products/v1/get_products_test.go +++ b/internal/services/catalog_write_service/test/integration/products/features/getting_products/v1/get_products_test.go @@ -9,8 +9,8 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/dtos" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/queries" + getProductsQueryV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" "github.com/mehdihadeli/go-mediatr" @@ -31,7 +31,7 @@ var _ = Describe("Get All Products Feature", func() { // Define variables to hold query and result data var ( ctx context.Context - query *queries.GetProducts + query *getProductsQueryV1.GetProducts queryResult *dtos.GetProductsResponseDto err error ) @@ -74,30 +74,38 @@ var _ = Describe("Get All Products Feature", func() { }) // "When" step - When("the GteProducts query is executed for existing products", func() { - BeforeEach(func() { - queryResult, err = mediatr.Send[*queries.GetProducts, *dtos.GetProductsResponseDto](ctx, query) - }) - - // "Then" step - It("Should not return an error", func() { - Expect(err).To(BeNil()) - }) - - It("Should return a non-nil result", func() { - Expect(queryResult).NotTo(BeNil()) - }) - - It("Should return a list of products with items", func() { - Expect(queryResult.Products).NotTo(BeNil()) - Expect(queryResult.Products.Items).NotTo(BeEmpty()) - }) - - It("Should return the expected number of products", func() { - // Replace 'len(c.Items)' with the expected number of products - Expect(len(queryResult.Products.Items)).To(Equal(len(integrationFixture.Items))) - }) - }) + When( + "the GteProducts query is executed for existing products", + func() { + BeforeEach(func() { + queryResult, err = mediatr.Send[*queries.GetProducts, *dtos.GetProductsResponseDto]( + ctx, + query, + ) + }) + + // "Then" step + It("Should not return an error", func() { + Expect(err).To(BeNil()) + }) + + It("Should return a non-nil result", func() { + Expect(queryResult).NotTo(BeNil()) + }) + + It("Should return a list of products with items", func() { + Expect(queryResult.Products).NotTo(BeNil()) + Expect(queryResult.Products.Items).NotTo(BeEmpty()) + }) + + It("Should return the expected number of products", func() { + // Replace 'len(c.Items)' with the expected number of products + Expect( + len(queryResult.Products.Items), + ).To(Equal(len(integrationFixture.Items))) + }) + }, + ) }) }) }) diff --git a/internal/services/catalog_write_service/test/integration/products/features/updating_product/v1/update_product_test.go b/internal/services/catalog_write_service/test/integration/products/features/updating_product/v1/update_product_test.go index 5ef22d36..d261a240 100644 --- a/internal/services/catalog_write_service/test/integration/products/features/updating_product/v1/update_product_test.go +++ b/internal/services/catalog_write_service/test/integration/products/features/updating_product/v1/update_product_test.go @@ -13,8 +13,8 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/hypothesis" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/commands" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/events/integration_events" + v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/events/integrationevents" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" @@ -38,11 +38,11 @@ var _ = Describe("Update Product Feature", func() { var ( ctx context.Context existingProduct *models.Product - command *commands.UpdateProduct + command *v1.UpdateProduct result *mediatr.Unit err error id uuid.UUID - shouldPublish hypothesis.Hypothesis[*integration_events.ProductUpdatedV1] + shouldPublish hypothesis.Hypothesis[*integrationevents.ProductUpdatedV1] ) _ = BeforeEach(func() { @@ -79,7 +79,7 @@ var _ = Describe("Update Product Feature", func() { Describe("Updating an existing product in the database", func() { Context("Given product exists in the database", func() { BeforeEach(func() { - command, err = commands.NewUpdateProduct( + command, err = v1.NewUpdateProduct( existingProduct.ProductId, "Updated Product Name", existingProduct.Description, @@ -91,7 +91,7 @@ var _ = Describe("Update Product Feature", func() { // "When" step When("the UpdateProduct command is executed", func() { BeforeEach(func() { - result, err = mediatr.Send[*commands.UpdateProduct, *mediatr.Unit](ctx, command) + result, err = mediatr.Send[*v1.UpdateProduct, *mediatr.Unit](ctx, command) }) // "Then" step @@ -125,7 +125,7 @@ var _ = Describe("Update Product Feature", func() { BeforeEach(func() { // Generate a random ID that does not exist in the database id = uuid.NewV4() - command, err = commands.NewUpdateProduct( + command, err = v1.NewUpdateProduct( id, "Updated Product Name", "Updated Product Description", @@ -137,7 +137,7 @@ var _ = Describe("Update Product Feature", func() { // "When" step When("the UpdateProduct command executed for non-existing product", func() { BeforeEach(func() { - result, err = mediatr.Send[*commands.UpdateProduct, *mediatr.Unit](ctx, command) + result, err = mediatr.Send[*v1.UpdateProduct, *mediatr.Unit](ctx, command) }) // "Then" step @@ -164,7 +164,7 @@ var _ = Describe("Update Product Feature", func() { Describe("Publishing ProductUpdated when product updated successfully", func() { Context("Given product exists in the database", func() { BeforeEach(func() { - command, err = commands.NewUpdateProduct( + command, err = v1.NewUpdateProduct( existingProduct.ProductId, "Updated Product Name", existingProduct.Description, @@ -172,7 +172,7 @@ var _ = Describe("Update Product Feature", func() { ) Expect(err).NotTo(HaveOccurred()) - shouldPublish = messaging.ShouldProduced[*integration_events.ProductUpdatedV1]( + shouldPublish = messaging.ShouldProduced[*integrationevents.ProductUpdatedV1]( ctx, integrationFixture.Bus, nil, @@ -182,7 +182,7 @@ var _ = Describe("Update Product Feature", func() { // "When" step When("the UpdateProduct command is executed for existing product", func() { BeforeEach(func() { - result, err = mediatr.Send[*commands.UpdateProduct, *mediatr.Unit](ctx, command) + result, err = mediatr.Send[*v1.UpdateProduct, *mediatr.Unit](ctx, command) }) It("Should publish ProductUpdated event to the broker", func() { diff --git a/internal/services/catalog_write_service/test/unit/products/features/creating_product/v1/commands/create_product_handler_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/creating_product/v1/commands/create_product_handler_unit_test.go index 8662a280..06a382be 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/creating_product/v1/commands/create_product_handler_unit_test.go +++ b/internal/services/catalog_write_service/test/unit/products/features/creating_product/v1/commands/create_product_handler_unit_test.go @@ -12,7 +12,7 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - createProductCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/commands" + createProductCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/commands" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/mocks/testData" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" diff --git a/internal/services/catalog_write_service/test/unit/products/features/creating_product/v1/commands/create_product_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/creating_product/v1/commands/create_product_unit_test.go index 22d67ced..e409c6f7 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/creating_product/v1/commands/create_product_unit_test.go +++ b/internal/services/catalog_write_service/test/unit/products/features/creating_product/v1/commands/create_product_unit_test.go @@ -6,7 +6,7 @@ package commands import ( "testing" - createProductCommand "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creating_product/v1/commands" + createProductCommand "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/commands" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" "github.com/brianvoe/gofakeit/v6" diff --git a/internal/services/catalog_write_service/test/unit/products/features/deleting_product/v1/commands/delete_product_handler_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/deleting_product/v1/commands/delete_product_handler_unit_test.go index d6f49bac..3fed6f27 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/deleting_product/v1/commands/delete_product_handler_unit_test.go +++ b/internal/services/catalog_write_service/test/unit/products/features/deleting_product/v1/commands/delete_product_handler_unit_test.go @@ -9,7 +9,7 @@ import ( "testing" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1/commands" + v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" "emperror.dev/errors" @@ -35,7 +35,7 @@ func (c *deleteProductHandlerUnitTests) Test_Handle_Should_Delete_Product_With_V ctx := context.Background() id := c.Items[0].ProductId - deleteProduct := &commands.DeleteProduct{ + deleteProduct := &v1.DeleteProduct{ ProductID: id, } @@ -43,7 +43,7 @@ func (c *deleteProductHandlerUnitTests) Test_Handle_Should_Delete_Product_With_V Once(). Return(nil) - deleteProductHandler := commands.NewDeleteProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) + deleteProductHandler := v1.NewDeleteProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) _, err := deleteProductHandler.Handle(ctx, deleteProduct) c.Require().NoError(err) @@ -57,7 +57,7 @@ func (c *deleteProductHandlerUnitTests) Test_Handle_Should_Return_NotFound_Error ctx := context.Background() id := uuid.NewV4() - deleteProduct := &commands.DeleteProduct{ + deleteProduct := &v1.DeleteProduct{ ProductID: id, } @@ -65,7 +65,7 @@ func (c *deleteProductHandlerUnitTests) Test_Handle_Should_Return_NotFound_Error Once(). Return(customErrors.NewNotFoundError("error finding product")) - deleteProductHandler := commands.NewDeleteProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) + deleteProductHandler := v1.NewDeleteProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) res, err := deleteProductHandler.Handle(ctx, deleteProduct) c.Require().Error(err) @@ -82,7 +82,7 @@ func (c *deleteProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Erro ctx := context.Background() id := c.Items[0].ProductId - deleteProduct := &commands.DeleteProduct{ + deleteProduct := &v1.DeleteProduct{ ProductID: id, } @@ -97,7 +97,7 @@ func (c *deleteProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Erro Once(). Return(errors.New("error in the publish message")) - deleteProductHandler := commands.NewDeleteProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) + deleteProductHandler := v1.NewDeleteProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) dto, err := deleteProductHandler.Handle(ctx, deleteProduct) c.NotNil(dto) diff --git a/internal/services/catalog_write_service/test/unit/products/features/deleting_product/v1/commands/delete_product_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/deleting_product/v1/commands/delete_product_unit_test.go index 0ed12e9b..ceb292f9 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/deleting_product/v1/commands/delete_product_unit_test.go +++ b/internal/services/catalog_write_service/test/unit/products/features/deleting_product/v1/commands/delete_product_unit_test.go @@ -6,7 +6,7 @@ package commands import ( "testing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1/commands" + v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" uuid "github.com/satori/go.uuid" @@ -27,7 +27,7 @@ func TestDeleteProductByIdUnit(t *testing.T) { func (c *deleteProductUnitTests) Test_New_Delete_Product_Should_Return_No_Error_For_Valid_Input() { id := uuid.NewV4() - query, err := commands.NewDeleteProduct(id) + query, err := v1.NewDeleteProduct(id) c.Assert().NotNil(query) c.Assert().Equal(query.ProductID, id) @@ -35,7 +35,7 @@ func (c *deleteProductUnitTests) Test_New_Delete_Product_Should_Return_No_Error_ } func (c *deleteProductUnitTests) Test_New_Delete_Product_Should_Return_Error_For_Invalid_Id() { - query, err := commands.NewDeleteProduct(uuid.UUID{}) + query, err := v1.NewDeleteProduct(uuid.UUID{}) c.Assert().Nil(query) c.Require().Error(err) diff --git a/internal/services/catalog_write_service/test/unit/products/features/getting_product_by_id/v1/queries/get_product_by_Id_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/getting_product_by_id/v1/queries/get_product_by_Id_unit_test.go index f16e6d99..feca8ee2 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/getting_product_by_id/v1/queries/get_product_by_Id_unit_test.go +++ b/internal/services/catalog_write_service/test/unit/products/features/getting_product_by_id/v1/queries/get_product_by_Id_unit_test.go @@ -6,7 +6,7 @@ package queries import ( "testing" - getProductByIdQuery "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/queries" + getProductByIdQuery "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" uuid "github.com/satori/go.uuid" diff --git a/internal/services/catalog_write_service/test/unit/products/features/getting_product_by_id/v1/queries/get_product_by_id_handler_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/getting_product_by_id/v1/queries/get_product_by_id_handler_unit_test.go index 97b6c89d..74bc3044 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/getting_product_by_id/v1/queries/get_product_by_id_handler_unit_test.go +++ b/internal/services/catalog_write_service/test/unit/products/features/getting_product_by_id/v1/queries/get_product_by_id_handler_unit_test.go @@ -11,7 +11,7 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - getProductByIdQueryV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/queries" + v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" @@ -93,7 +93,7 @@ func (c *getProductByIdHandlerTest) Test_Get_Product_By_Id() { // create new mocks or clear mocks before executing c.CleanupMocks() - getProductByIdHandler := getProductByIdQueryV1.NewGetProductByIdHandler( + getProductByIdHandler := v1.NewGetProductByIDHandler( c.Log, c.ProductRepository, c.Tracer, @@ -107,7 +107,7 @@ func (c *getProductByIdHandlerTest) Test_Get_Product_By_Id() { testCase.fn() } - query, err := getProductByIdQueryV1.NewGetProductById(testCase.id) + query, err := v1.NewGetProductById(testCase.id) c.Require().NoError(err) // act diff --git a/internal/services/catalog_write_service/test/unit/products/features/getting_products/v1/queries/get_products_handler_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/getting_products/v1/queries/get_products_handler_unit_test.go index ab76b0af..43ec49b9 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/getting_products/v1/queries/get_products_handler_unit_test.go +++ b/internal/services/catalog_write_service/test/unit/products/features/getting_products/v1/queries/get_products_handler_unit_test.go @@ -10,7 +10,7 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/queries" + getting_products2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/mocks/testData" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" @@ -34,7 +34,7 @@ func TestGetProductsUnit(t *testing.T) { func (c *getProductsHandlerUnitTests) Test_Handle_Should_Return_Products_Successfully() { ctx := context.Background() - query, err := queries.NewGetProducts(utils.NewListQuery(10, 1)) + query, err := getting_products2.NewGetProducts(utils.NewListQuery(10, 1)) c.Require().NoError(err) items := utils.NewListResult[*models.Product]( @@ -47,7 +47,7 @@ func (c *getProductsHandlerUnitTests) Test_Handle_Should_Return_Products_Success Once(). Return(items, nil) - getProductsHandler := queries.NewGetProductsHandler(c.Log, c.ProductRepository, c.Tracer) + getProductsHandler := getting_products2.NewGetProductsHandler(c.Log, c.ProductRepository, c.Tracer) res, err := getProductsHandler.Handle(ctx, query) c.Require().NoError(err) diff --git a/internal/services/catalog_write_service/test/unit/products/features/updating_product/v1/commands/update_product_handler_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/updating_product/v1/commands/update_product_handler_unit_test.go index e232d388..cbc520a2 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/updating_product/v1/commands/update_product_handler_unit_test.go +++ b/internal/services/catalog_write_service/test/unit/products/features/updating_product/v1/commands/update_product_handler_unit_test.go @@ -9,7 +9,7 @@ import ( "testing" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/commands" + v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" @@ -37,7 +37,7 @@ func (c *updateProductHandlerUnitTests) Test_Handle_Should_Update_Product_With_V ctx := context.Background() existing := c.Items[0] - updateProductCommand, err := commands.NewUpdateProduct( + updateProductCommand, err := v1.NewUpdateProduct( existing.ProductId, gofakeit.Name(), gofakeit.EmojiDescription(), @@ -62,7 +62,7 @@ func (c *updateProductHandlerUnitTests) Test_Handle_Should_Update_Product_With_V Once(). Return(updated, nil) - updateProductHandler := commands.NewUpdateProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) + updateProductHandler := v1.NewUpdateProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) _, err = updateProductHandler.Handle(ctx, updateProductCommand) c.Require().NoError(err) @@ -77,7 +77,7 @@ func (c *updateProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_NotF ctx := context.Background() id := uuid.NewV4() - command, err := commands.NewUpdateProduct( + command, err := v1.NewUpdateProduct( id, gofakeit.Name(), gofakeit.EmojiDescription(), @@ -89,7 +89,7 @@ func (c *updateProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_NotF Once(). Return(nil, errors.New("error notfound product")) - updateProductHandler := commands.NewUpdateProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) + updateProductHandler := v1.NewUpdateProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) dto, err := updateProductHandler.Handle(ctx, command) c.Uow.AssertNumberOfCalls(c.T(), "Do", 1) @@ -105,7 +105,7 @@ func (c *updateProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Erro ctx := context.Background() existing := c.Items[0] - updateProductCommand, err := commands.NewUpdateProduct( + updateProductCommand, err := v1.NewUpdateProduct( existing.ProductId, gofakeit.Name(), gofakeit.EmojiDescription(), @@ -137,7 +137,7 @@ func (c *updateProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Erro Once(). Return(errors.New("error in the publish message")) - updateProductHandler := commands.NewUpdateProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) + updateProductHandler := v1.NewUpdateProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) dto, err := updateProductHandler.Handle(ctx, updateProductCommand) c.Uow.AssertNumberOfCalls(c.T(), "Do", 1) diff --git a/internal/services/catalog_write_service/test/unit/products/features/updating_product/v1/commands/update_product_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/updating_product/v1/commands/update_product_unit_test.go index 5041a308..9b2d19ec 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/updating_product/v1/commands/update_product_unit_test.go +++ b/internal/services/catalog_write_service/test/unit/products/features/updating_product/v1/commands/update_product_unit_test.go @@ -6,7 +6,7 @@ package commands import ( "testing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/commands" + v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" "github.com/brianvoe/gofakeit/v6" @@ -31,7 +31,7 @@ func (c *updateProductUnitTests) Test_New_Update_Product_Should_Return_No_Error_ description := gofakeit.EmojiDescription() price := gofakeit.Price(150, 6000) - updateProduct, err := commands.NewUpdateProduct(id, name, description, price) + updateProduct, err := v1.NewUpdateProduct(id, name, description, price) c.Assert().NotNil(updateProduct) c.Assert().Equal(id, updateProduct.ProductID) @@ -42,7 +42,7 @@ func (c *updateProductUnitTests) Test_New_Update_Product_Should_Return_No_Error_ } func (c *updateProductUnitTests) Test_New_Update_Product_Should_Return_Error_For_Invalid_Price() { - command, err := commands.NewUpdateProduct( + command, err := v1.NewUpdateProduct( uuid.NewV4(), gofakeit.Name(), gofakeit.EmojiDescription(), @@ -54,14 +54,14 @@ func (c *updateProductUnitTests) Test_New_Update_Product_Should_Return_Error_For } func (c *updateProductUnitTests) Test_New_Update_Product_Should_Return_Error_For_Empty_Name() { - command, err := commands.NewUpdateProduct(uuid.NewV4(), "", gofakeit.EmojiDescription(), 120) + command, err := v1.NewUpdateProduct(uuid.NewV4(), "", gofakeit.EmojiDescription(), 120) c.Require().Error(err) c.Assert().Nil(command) } func (c *updateProductUnitTests) Test_New_Update_Product_Should_Return_Error_For_Empty_Description() { - command, err := commands.NewUpdateProduct(uuid.NewV4(), gofakeit.Name(), "", 120) + command, err := v1.NewUpdateProduct(uuid.NewV4(), gofakeit.Name(), "", 120) c.Require().Error(err) c.Assert().Nil(command) diff --git a/internal/services/catalog_write_service/test/unit/products/mappings_profile_test.go b/internal/services/catalog_write_service/test/unit/products/mappings_profile_test.go index ad2def27..ac523994 100644 --- a/internal/services/catalog_write_service/test/unit/products/mappings_profile_test.go +++ b/internal/services/catalog_write_service/test/unit/products/mappings_profile_test.go @@ -8,7 +8,7 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dto/v1" + dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" diff --git a/internal/services/order_service/config/config.go b/internal/services/order_service/config/config.go index 9f60cc2e..5348a876 100644 --- a/internal/services/order_service/config/config.go +++ b/internal/services/order_service/config/config.go @@ -4,14 +4,14 @@ import ( "strings" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" ) type Config struct { AppOptions AppOptions `mapstructure:"appOptions"` } -func NewConfig(environment environemnt.Environment) (*Config, error) { +func NewConfig(environment environment.Environment) (*Config, error) { cfg, err := config.BindConfig[*Config](environment) if err != nil { return nil, err diff --git a/internal/services/order_service/go.mod b/internal/services/order_service/go.mod index bf950584..ceb5850d 100644 --- a/internal/services/order_service/go.mod +++ b/internal/services/order_service/go.mod @@ -16,7 +16,7 @@ require ( github.com/goccy/go-json v0.10.2 github.com/labstack/echo/v4 v4.11.1 github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg v0.0.0-20230831075934-be8df319f588 - github.com/mehdihadeli/go-mediatr v1.2.0 + github.com/mehdihadeli/go-mediatr v1.3.0 github.com/michaelklishin/rabbit-hole v1.5.0 github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.28.0 diff --git a/internal/services/order_service/go.sum b/internal/services/order_service/go.sum index 09c7866e..d849c313 100644 --- a/internal/services/order_service/go.sum +++ b/internal/services/order_service/go.sum @@ -521,6 +521,8 @@ github.com/mehdihadeli/go-mediatr v1.1.10 h1:NAzg4065c90lgYeb+Vzbd2WKH0tUFpxzL0m github.com/mehdihadeli/go-mediatr v1.1.10/go.mod h1:lwgZl7qVL/RKomObBblhG3uEte/r4nJDV95Vd+nGrMw= github.com/mehdihadeli/go-mediatr v1.2.0 h1:XkzYF/uGfW4pwPWYAxKyY+mO6l989PbmCQWSYHuCZtU= github.com/mehdihadeli/go-mediatr v1.2.0/go.mod h1:I9LuExxAKz6cTDJyP/SSDSmkHaPHK1/usnvEXjUY47k= +github.com/mehdihadeli/go-mediatr v1.3.0 h1:hrb5Scp/nsiR3Y62mjZ0Tc5UX/dRJl4nDFkINBEIESA= +github.com/mehdihadeli/go-mediatr v1.3.0/go.mod h1:lsG+hyH+pEOhmZiZl0KPO72BcZiEReF03CBk4GVJB0k= github.com/michaelklishin/rabbit-hole v1.5.0 h1:Bex27BiFDsijCM9D0ezSHqyy0kehpYHuNKaPqq/a4RM= github.com/michaelklishin/rabbit-hole v1.5.0/go.mod h1:vvI1uOitYZi0O5HEGXhaWC1XT80Gy+HvFheJ+5Krlhk= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= diff --git a/internal/services/order_service/internal/orders/configurations/orders_module_configurator.go b/internal/services/order_service/internal/orders/configurations/orders_module_configurator.go index fb831bf2..53470b32 100644 --- a/internal/services/order_service/internal/orders/configurations/orders_module_configurator.go +++ b/internal/services/order_service/internal/orders/configurations/orders_module_configurator.go @@ -1,13 +1,13 @@ package configurations import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/contracts/store" contracts2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" grpcServer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc" customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/configurations/mappings" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/configurations/mediatr" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/contracts/repositories" diff --git a/internal/services/order_service/internal/orders/features/creating_order/v1/endpoints/create_order_endpoint.go b/internal/services/order_service/internal/orders/features/creating_order/v1/endpoints/create_order_endpoint.go index ddf25504..5dff96b1 100644 --- a/internal/services/order_service/internal/orders/features/creating_order/v1/endpoints/create_order_endpoint.go +++ b/internal/services/order_service/internal/orders/features/creating_order/v1/endpoints/create_order_endpoint.go @@ -5,9 +5,9 @@ import ( "net/http" "time" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/contracts/params" createOrderCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/creating_order/v1/commands" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/creating_order/v1/dtos" diff --git a/internal/services/order_service/internal/orders/features/getting_order_by_id/v1/endpoints/get_order_by_id_endpoint.go b/internal/services/order_service/internal/orders/features/getting_order_by_id/v1/endpoints/get_order_by_id_endpoint.go index c193c9ab..a1933b61 100644 --- a/internal/services/order_service/internal/orders/features/getting_order_by_id/v1/endpoints/get_order_by_id_endpoint.go +++ b/internal/services/order_service/internal/orders/features/getting_order_by_id/v1/endpoints/get_order_by_id_endpoint.go @@ -4,9 +4,9 @@ import ( "fmt" "net/http" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/contracts/params" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/queries" diff --git a/internal/services/order_service/internal/orders/features/getting_orders/v1/endpoints/get_orders_endpoint.go b/internal/services/order_service/internal/orders/features/getting_orders/v1/endpoints/get_orders_endpoint.go index d0c0ad3d..f441837e 100644 --- a/internal/services/order_service/internal/orders/features/getting_orders/v1/endpoints/get_orders_endpoint.go +++ b/internal/services/order_service/internal/orders/features/getting_orders/v1/endpoints/get_orders_endpoint.go @@ -4,9 +4,9 @@ import ( "fmt" "net/http" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/contracts/params" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/getting_orders/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/getting_orders/v1/queries" diff --git a/internal/services/order_service/internal/orders/orders_fx.go b/internal/services/order_service/internal/orders/orders_fx.go index ffe80cad..e418fd82 100644 --- a/internal/services/order_service/internal/orders/orders_fx.go +++ b/internal/services/order_service/internal/orders/orders_fx.go @@ -1,10 +1,10 @@ package orders import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/eventstroredb" customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/data/repositories" createOrderV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/creating_order/v1/endpoints" getOrderByIdV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/endpoints" diff --git a/internal/services/order_service/internal/shared/app/application.go b/internal/services/order_service/internal/shared/app/application.go index fdb4b135..fd57ba9c 100644 --- a/internal/services/order_service/internal/shared/app/application.go +++ b/internal/services/order_service/internal/shared/app/application.go @@ -1,7 +1,7 @@ package app import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/shared/configurations/orders" @@ -18,7 +18,7 @@ func NewOrdersApplication( decorates []interface{}, options []fx.Option, logger logger.Logger, - environment environemnt.Environment, + environment environment.Environment, ) *OrdersApplication { app := fxapp.NewApplication(providers, decorates, options, logger, environment) return &OrdersApplication{ diff --git a/internal/services/order_service/internal/shared/app/test/test_application.go b/internal/services/order_service/internal/shared/app/test/test_application.go index 206f15a2..1f205ea2 100644 --- a/internal/services/order_service/internal/shared/app/test/test_application.go +++ b/internal/services/order_service/internal/shared/app/test/test_application.go @@ -1,7 +1,7 @@ package test import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environemnt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/test" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/shared/app" @@ -22,7 +22,7 @@ func NewOrdersTestApplication( decorates []interface{}, options []fx.Option, logger logger.Logger, - environment environemnt.Environment, + environment environment.Environment, ) *OrdersTestApplication { testApp := test.NewTestApplication( tb, diff --git a/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go b/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go index 54fcd8e9..35130df2 100644 --- a/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go +++ b/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go @@ -5,9 +5,9 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/pipelines" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" - pipelines2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/pipelines" + pipelines2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/mediatr/pipelines" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - tracingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/pipelines" + tracingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/mediatr/pipelines" "github.com/mehdihadeli/go-mediatr" ) @@ -29,11 +29,11 @@ func (ic *InfrastructureConfigurator) ConfigInfrastructures() { func(logger logger.Logger, tracer tracing.AppTracer, metrics metrics.AppMetrics) error { err := mediatr.RegisterRequestPipelineBehaviors( pipelines.NewLoggingPipeline(logger), - tracingpipelines.NewTracingPipeline( + tracingpipelines.NewMediatorTracingPipeline( tracer, tracingpipelines.WithLogger(logger), ), - pipelines2.NewMetricsPipeline( + pipelines2.NewMediatorMetricsPipeline( metrics, pipelines2.WithLogger(logger), ), diff --git a/scripts/install-tools.sh b/scripts/install-tools.sh index e6f4c72d..4b60b113 100644 --- a/scripts/install-tools.sh +++ b/scripts/install-tools.sh @@ -7,6 +7,8 @@ set -e # `go install package@version` command works directly when we specified exact version, elsewhere it needs a `go.mod` and specifying corresponding version for each package +go install github.com/samlitowitz/goimportcycle/cmd/goimportcycle@latest + # https://github.com/incu6us/goimports-reviser go install -v github.com/incu6us/goimports-reviser/v3@latest From dfa600be0173c6e7b0c4c750b294a99324c86e11 Mon Sep 17 00:00:00 2001 From: mehdihadeli Date: Tue, 28 Nov 2023 19:40:29 +0330 Subject: [PATCH 08/15] feat: :sparkles: removing repository and uow for gorm DataAccess #95 --- internal/pkg/config/config_helper.go | 2 +- .../pkg/config/environment/environment.go | 20 + internal/pkg/core/cqrs/tx_request.go | 6 + .../custom_time.go | 0 internal/pkg/core/messaging/bus/bus.go | 12 + .../{ => core}/messaging/consumer/consumer.go | 2 +- .../messaging/consumer/consumer_builder.go | 0 .../messaging/consumer/consumer_connector.go | 2 +- .../messaging/consumer/consumer_handler.go | 2 +- .../consumer_handler_configuration.go | 0 .../consumer_handler_configuration_builder.go | 0 .../messaging/consumer/consumer_options.go | 0 .../messaging/consumer/consumers_control.go | 2 +- .../messageheader}/message_header.go | 0 .../metadata_message_extentions.go | 0 .../pkg/{ => core}/messaging/mocks/Bus.go | 29 +- .../{ => core}/messaging/mocks/BusControl.go | 6 +- .../{ => core}/messaging/mocks/Consumer.go | 8 +- .../messaging/mocks/ConsumerBuilderFucT.go | 0 .../messaging/mocks/ConsumerConnector.go | 29 +- .../messaging/mocks/ConsumerHandler.go | 6 +- .../ConsumerHandlerConfigurationBuilder.go | 34 +- ...ConsumerHandlerConfigurationBuilderFunc.go | 6 +- .../messaging/mocks/ConsumerHandlerFunc.go | 0 .../messaging/mocks/ConsumerPipeline.go | 8 +- .../ConsumerPipelineConfigurationBuilder.go | 31 +- ...onsumerPipelineConfigurationBuilderFunc.go | 6 +- .../{ => core}/messaging/mocks/IMessage.go | 0 .../messaging/mocks/MessageConsumeContext.go | 11 +- .../{ => core}/messaging/mocks/Producer.go | 7 +- .../messaging/mocks/ProducerBuilderFuc.go | 0 .../messaging/otel/tracing/consts.go | 0 .../otel/tracing/consumer/consumer.go | 18 +- .../consumer/consumer_tracing_options.go | 0 .../messaging/otel/tracing/message_carrier.go | 0 .../otel/tracing/producer/producer.go | 20 +- .../producer/producer_tracing_options.go | 0 .../messaging/otel/tracing/trace.go | 0 .../message_persistence_repository.go | 21 + .../message_persistence_service.go | 24 + .../messaging/persistmessage/store_message.go | 53 ++ .../messaging/pipeline/consumer_pipeline.go | 2 +- .../consumer_pipeline_configuration.go | 0 ...consumer_pipeline_configuration_builder.go | 0 .../{ => core}/messaging/producer/producer.go | 2 +- .../messaging/producer/producer_builder.go | 0 .../pkg/{ => core}/messaging/types/message.go | 0 .../types/message_consume_context.go | 0 .../core/messaging/types/message_envelope.go | 37 + .../messaging/types/mock_IMessage_test.go | 0 .../pkg/{ => core}/messaging/utils/utils.go | 4 +- .../pkg/core/serializer/event_serializer.go | 4 +- internal/pkg/core/utils/utils.go | 2 +- internal/pkg/elasticsearch/elastic_options.go | 2 +- internal/pkg/eventstroredb/aggregate_store.go | 2 +- .../config/eventstoredb_options.go | 2 +- internal/pkg/eventstroredb/esdb_serilizer.go | 2 +- ...sdb_subscription_check_point_repository.go | 2 +- .../eventstroredb/subscription_all_worker.go | 2 +- internal/pkg/fxapp/test/test_application.go | 29 +- internal/pkg/go.mod | 12 +- internal/pkg/go.sum | 12 +- .../gorm_generic_repository_test.go | 510 ------------ internal/pkg/grpc/config/grpc_options.go | 2 +- internal/pkg/grpc/grpcErrors/grpc_errors.go | 2 +- .../custom_echo/config/echo_http_options.go | 2 +- .../problemDetails/problem_detail_parser.go | 2 +- .../problemDetails/problem_details.go | 4 +- internal/pkg/logger/config/log_options.go | 2 +- .../default_logger.go | 0 .../pkg/logger/pipelines/logging_pipeline.go | 6 +- internal/pkg/mapper/mapper.go | 4 +- internal/pkg/messaging/bus/bus.go | 12 - internal/pkg/migration/goose/postgres.go | 21 +- internal/pkg/migration/migration_options.go | 2 +- internal/pkg/mongodb/helpers.go | 37 +- internal/pkg/mongodb/mongo_options.go | 2 +- .../repository/mongo_generic_repository.go | 75 +- .../mongo_generic_repository_test.go | 742 +++++++++--------- .../constants/telemetry_attributes/app/app.go | 26 - .../exception/exception.go | 8 - .../telemetry_attributes/general/general.go | 1 - .../telemetry_attributes/grpc/grpc.go | 3 - .../messaging/messaging.go | 14 - .../constants/telemetry_attributes/net/net.go | 11 - .../constants/telemetrytags/telemetrytags.go | 119 +++ .../otel/metrics/mediatr/pipelines/config.go | 2 +- .../pipelines/mediator_metrics_pipeline.go | 58 +- .../otel/metrics/messaging/pipeline/config.go | 2 +- .../pipeline/messaging_metrics_pipeline.go | 6 +- internal/pkg/otel/metrics/metrics_options.go | 2 +- .../otel/tracing/mediatr/pipelines/config.go | 2 +- .../pipelines/mediator_tracing_pipeline.go | 52 +- internal/pkg/otel/tracing/tracing_options.go | 2 +- internal/pkg/otel/tracing/utils/utils.go | 26 +- .../pkg/postgresGorm/constants/constants.go | 5 + .../postgresGorm/contracts/gorm_context.go | 12 + .../pkg/{gorm_postgres => postgresGorm}/db.go | 61 +- .../gorm_options.go | 5 +- .../gorm_options_test.go | 2 +- .../gorm_postgres_fx.go | 2 +- .../{gorm_postgres => postgresGorm}/health.go | 2 +- .../helpers.go | 37 +- internal/pkg/postgresGorm/helpers/helpers.go | 32 + .../mediator_transaction_pipeline.go | 94 +++ .../repository/gorm_generic_repository.go | 158 ++-- .../gorm_generic_repository_test.go | 496 ++++++++++++ .../message_persistence_dbcontext.go | 38 + .../message_persistence_repository.go | 87 ++ .../interface.go | 0 .../{postgres_pgx => postgrespgx}/postgres.go | 0 .../postgres_pgx_fx.go | 0 .../postgres_pgx_options.go | 2 +- .../postgres.go | 0 .../postgres_sqlx_fx.go | 0 .../postgres_sqlx_options.go | 2 +- internal/pkg/rabbitmq/bus/rabbitmq-bus.go | 24 +- .../pkg/rabbitmq/bus/rabbitmq_bus_test.go | 26 +- .../pkg/rabbitmq/config/rabbitmq_options.go | 2 +- .../rabbitmq_configuration_builder.go | 2 +- .../configurations/consumer_connector.go | 4 +- .../rabbitmq_consumer_configuration.go | 14 +- ...rabbitmq_consumer_configuration_builder.go | 6 +- .../consumercontracts/consumer_factory.go | 4 +- .../consumer/factory/consumer_factory.go | 4 +- .../rabbitmq/consumer/rabbitmq_consumer.go | 62 +- .../consumer/rabbitmq_consumer_test.go | 18 +- .../rabbitmq_producer_configuration.go | 4 +- .../rabitmq_producer_configuration_builder.go | 2 +- .../pkg/rabbitmq/producer/producer_factory.go | 4 +- .../producercontracts/producer_factory.go | 4 +- .../rabbitmq/producer/rabbitmq_producer.go | 32 +- .../producer/rabbitmq_producer_test.go | 4 +- internal/pkg/rabbitmq/rabbitmq_fx.go | 4 +- .../test/in-memory/rabbitmq_harnes.go | 10 +- internal/pkg/rabbitmq/types/connection.go | 2 +- internal/pkg/redis/redis_options.go | 2 +- .../reflection_helper.go | 0 .../reflection_helper_test.go | 0 .../type_mapper.go | 24 + .../type_mapper_test.go | 0 .../unsafe_types.go | 0 .../type_registry.go | 2 +- .../containers/contracts/gorm_container.go | 2 +- .../contracts/postgrespgx_container.go | 2 +- .../dockertest/gorm/gorm_container.go | 2 +- .../dockertest/gorm/gorm_container_test.go | 2 +- .../containers/dockertest/gorm/gorm_fx.go | 2 +- .../rabbitmq/rabbitmq_container_test.go | 6 +- .../containers/gnomock/gorm/gorm_container.go | 2 +- .../testcontainer/gorm/gorm_container.go | 2 +- .../testcontainer/gorm/gorm_container_test.go | 2 +- .../containers/testcontainer/gorm/gorm_fx.go | 2 +- .../postgrespxg/postgrespgx_container.go | 2 +- .../postgrespxg/postgrespgx_container_test.go | 2 +- .../postgrespxg/postgrespgx_fx.go | 2 +- .../rabbitmq/rabbitmq_container_test.go | 6 +- .../consumer/rabbitmq_fake_consumer.go | 2 +- internal/pkg/test/messaging/utils.go | 8 +- internal/pkg/utils/error_utils/errors.go | 2 +- .../rabbitmq/rabbitmq_configuration.go | 2 +- .../externalevents/product_created.go | 2 +- .../product_created_consumer.go | 4 +- .../external_events/product_deleted.go | 2 +- .../product_deleted_consumer.go | 4 +- .../external_events/product_updated.go | 2 +- .../product_updated_consumer.go | 4 +- .../infrastructure_configurator.go | 17 +- .../integration/integration_test_fixture.go | 10 +- .../v1/get_product_by_id_test.go | 6 +- .../v1/get_products_endpoint_test.go | 6 +- .../data/mongo_product_repository_test.go | 6 +- .../v1/commands/create_product_test.go | 6 +- .../v1/events/product_created_test.go | 8 +- .../v1/commands/delete_product_test.go | 6 +- .../v1/events/product_deleted_test.go | 8 +- .../v1/queries/get_product_by_id_test.go | 6 +- .../v1/queries/get_products_handler_test.go | 6 +- .../commands/update_product_handler_test.go | 6 +- .../v1/events/product_updated_test.go | 8 +- .../cmd/migration/main.go | 4 +- .../config/app_options.go | 2 +- .../services/catalog_write_service/go.mod | 13 +- .../services/catalog_write_service/go.sum | 12 +- .../mappings/mapping_profile.go | 33 +- .../contracts/catalog_unit_of_work.go | 10 - .../products/contracts/catalogs_context.go | 8 - .../data/models/product_data_model.go | 33 + .../repositories/pg_product_repository.go | 2 +- .../products/data/uow/catalog_context.go | 13 - .../data/uow/catalogs_unit_of_work.go | 60 -- .../v1/fxparams/product_handler_params.go | 7 +- .../creatingproduct/v1/create_product.go | 5 + .../v1/create_product_handler.go | 110 ++- .../integrationevents/product_created.go | 2 +- .../v1/delete_product.go | 5 + .../v1/delete_product_endpoint.go | 2 +- .../v1/delete_product_handler.go | 73 +- .../v1/dtos/delete_product_request_dto.go | 0 .../integrationevents/product_deleted.go | 2 +- .../v1/get_products_handler.go | 20 +- .../v1/dtos/get_product_by_id_request_dto.go | 0 .../v1/dtos/get_product_by_id_response_dto.go | 0 .../v1/get_product_by_id.go | 0 .../v1/get_product_by_id_endpoint.go | 2 +- .../v1/get_product_by_id_handler.go | 22 +- .../v1/dtos/search_products_request_dto.go | 0 .../v1/dtos/search_products_response_dto.go | 0 .../v1/search_products.go | 0 .../v1/search_products_endpoint.go | 2 +- .../v1/search_products_handler.go | 41 +- .../v1/update_product_handler.go | 109 --- .../v1/dtos/update_product_request_dto.go | 0 .../integrationevents/product_updated.go | 2 +- .../v1/update_product.go | 31 +- .../v1/update_product_endpoint.go | 2 +- .../v1/update_product_handler.go | 112 +++ .../products/mocks/testData/products.go | 27 - .../internal/products/models/product.go | 18 +- .../internal/products/products_fx.go | 8 +- .../internal/shared/app/test/test_app.go | 13 +- .../catalogs/catalogs_configurator.go | 4 +- .../configurations/catalogs/catalogs_fx.go | 4 +- .../infrastructure_configurator.go | 17 +- .../infrastructure/infrastructure_fx.go | 2 +- .../internal/shared/data/data_fx.go | 18 + .../data/dbcontext/catalogs_dbcontext.go | 231 ++++++ .../data/dbcontext/catalogs_dbcontext_test.go | 212 +++++ .../grpc/product_grpc_service_server.go | 6 +- .../unit_test/unit_test_fixture.go | 116 --- .../integration/integration_test_fixture.go | 34 +- .../unittest/unit_test_fixture.go | 168 ++++ .../mocks/CatalogUnitOfWork.go | 81 -- .../mocks/CatalogUnitOfWorkActionFunc.go | 78 -- .../v1/create_product_test.go | 6 +- .../v1/delete_product_test.go | 6 +- .../v1/get_product_by_id_test.go | 6 +- .../gettingproducts}/v1/get_products_test.go | 6 +- .../v1/search_products_test.go | 6 +- .../v1/update_product_test.go | 8 +- .../grpc/product_grpc_service_server_test.go | 6 +- .../pg_product_repository_integration_test.go | 6 +- .../catalogs_unit_of_work_integration_test.go | 6 +- .../v1/create_product_test.go | 197 ----- .../creatingproduct/v1/create_product_test.go | 243 ++++++ .../v1/delete_product_test.go | 172 ++-- .../v1/get_product_by_id_test.go | 143 ---- .../v1/get_product_by_id_test.go | 166 ++++ .../v1/get_products_test.go | 26 +- .../v1/update_product_test.go | 177 +++-- .../create_product_handler_unit_test.go | 180 ----- .../v1/create_product_handler_unit_test.go | 164 ++++ .../v1}/create_product_unit_test.go | 30 +- .../delete_product_handler_unit_test.go | 110 --- .../v1/delete_product_handler_unit_test.go | 117 +++ .../v1}/delete_product_unit_test.go | 10 +- .../get_product_by_id_handler_unit_test.go | 209 ----- .../queries/get_products_handler_unit_test.go | 96 --- .../v1}/get_product_by_Id_unit_test.go | 10 +- .../v1/get_product_by_id_handler_unit_test.go | 97 +++ .../v1/get_products_handler_unit_test.go | 74 ++ .../v1/search_products_unit_test.go | 77 ++ .../update_product_handler_unit_test.go | 150 ---- .../v1/update_product_handler_unit_test.go | 133 ++++ .../v1}/update_product_unit_test.go | 10 +- .../unit/products/mappings_profile_test.go | 6 +- .../v1/dtos/create_order_request_dto.go | 2 +- .../v1/events/domain_events/order_created.go | 2 +- .../integration_events/order_created.go | 2 +- .../orders/models/orders/aggregate/order.go | 2 +- .../projections/mongo_order_projection.go | 2 +- .../infrastructure_configurator.go | 13 +- .../integration/integration_test_fixture.go | 10 +- .../creating_order/v1/create_order_test.go | 6 +- .../v1/get_order_by_id_test.go | 4 +- .../creating_order/v1/create_order_test.go | 4 +- .../v1/get_order_by_id_test.go | 4 +- 277 files changed, 4616 insertions(+), 3566 deletions(-) create mode 100644 internal/pkg/core/cqrs/tx_request.go rename internal/pkg/core/{custom_types => customtypes}/custom_time.go (100%) create mode 100644 internal/pkg/core/messaging/bus/bus.go rename internal/pkg/{ => core}/messaging/consumer/consumer.go (92%) rename internal/pkg/{ => core}/messaging/consumer/consumer_builder.go (100%) rename internal/pkg/{ => core}/messaging/consumer/consumer_connector.go (95%) rename internal/pkg/{ => core}/messaging/consumer/consumer_handler.go (90%) rename internal/pkg/{ => core}/messaging/consumer/consumer_handler_configuration.go (100%) rename internal/pkg/{ => core}/messaging/consumer/consumer_handler_configuration_builder.go (100%) rename internal/pkg/{ => core}/messaging/consumer/consumer_options.go (100%) rename internal/pkg/{ => core}/messaging/consumer/consumers_control.go (92%) rename internal/pkg/{messaging/message_header => core/messaging/messageheader}/message_header.go (100%) rename internal/pkg/{messaging/message_header => core/messaging/messageheader}/metadata_message_extentions.go (100%) rename internal/pkg/{ => core}/messaging/mocks/Bus.go (92%) rename internal/pkg/{ => core}/messaging/mocks/BusControl.go (97%) rename internal/pkg/{ => core}/messaging/mocks/Consumer.go (96%) rename internal/pkg/{ => core}/messaging/mocks/ConsumerBuilderFucT.go (100%) rename internal/pkg/{ => core}/messaging/mocks/ConsumerConnector.go (77%) rename internal/pkg/{ => core}/messaging/mocks/ConsumerHandler.go (95%) rename internal/pkg/{ => core}/messaging/mocks/ConsumerHandlerConfigurationBuilder.go (71%) rename internal/pkg/{ => core}/messaging/mocks/ConsumerHandlerConfigurationBuilderFunc.go (94%) rename internal/pkg/{ => core}/messaging/mocks/ConsumerHandlerFunc.go (100%) rename internal/pkg/{ => core}/messaging/mocks/ConsumerPipeline.go (92%) rename internal/pkg/{ => core}/messaging/mocks/ConsumerPipelineConfigurationBuilder.go (72%) rename internal/pkg/{ => core}/messaging/mocks/ConsumerPipelineConfigurationBuilderFunc.go (94%) rename internal/pkg/{ => core}/messaging/mocks/IMessage.go (100%) rename internal/pkg/{ => core}/messaging/mocks/MessageConsumeContext.go (98%) rename internal/pkg/{ => core}/messaging/mocks/Producer.go (98%) rename internal/pkg/{ => core}/messaging/mocks/ProducerBuilderFuc.go (100%) rename internal/pkg/{ => core}/messaging/otel/tracing/consts.go (100%) rename internal/pkg/{ => core}/messaging/otel/tracing/consumer/consumer.go (88%) rename internal/pkg/{ => core}/messaging/otel/tracing/consumer/consumer_tracing_options.go (100%) rename internal/pkg/{ => core}/messaging/otel/tracing/message_carrier.go (100%) rename internal/pkg/{ => core}/messaging/otel/tracing/producer/producer.go (91%) rename internal/pkg/{ => core}/messaging/otel/tracing/producer/producer_tracing_options.go (100%) rename internal/pkg/{ => core}/messaging/otel/tracing/trace.go (100%) create mode 100644 internal/pkg/core/messaging/persistmessage/message_persistence_repository.go create mode 100644 internal/pkg/core/messaging/persistmessage/message_persistence_service.go create mode 100644 internal/pkg/core/messaging/persistmessage/store_message.go rename internal/pkg/{ => core}/messaging/pipeline/consumer_pipeline.go (95%) rename internal/pkg/{ => core}/messaging/pipeline/consumer_pipeline_configuration.go (100%) rename internal/pkg/{ => core}/messaging/pipeline/consumer_pipeline_configuration_builder.go (100%) rename internal/pkg/{ => core}/messaging/producer/producer.go (95%) rename internal/pkg/{ => core}/messaging/producer/producer_builder.go (100%) rename internal/pkg/{ => core}/messaging/types/message.go (100%) rename internal/pkg/{ => core}/messaging/types/message_consume_context.go (100%) create mode 100644 internal/pkg/core/messaging/types/message_envelope.go rename internal/pkg/{ => core}/messaging/types/mock_IMessage_test.go (100%) rename internal/pkg/{ => core}/messaging/utils/utils.go (97%) delete mode 100644 internal/pkg/gorm_postgres/repository/gorm_generic_repository_test.go rename internal/pkg/logger/{default_logger => defaultlogger}/default_logger.go (100%) delete mode 100644 internal/pkg/messaging/bus/bus.go delete mode 100644 internal/pkg/otel/constants/telemetry_attributes/app/app.go delete mode 100644 internal/pkg/otel/constants/telemetry_attributes/exception/exception.go delete mode 100644 internal/pkg/otel/constants/telemetry_attributes/general/general.go delete mode 100644 internal/pkg/otel/constants/telemetry_attributes/grpc/grpc.go delete mode 100644 internal/pkg/otel/constants/telemetry_attributes/messaging/messaging.go delete mode 100644 internal/pkg/otel/constants/telemetry_attributes/net/net.go create mode 100644 internal/pkg/otel/constants/telemetrytags/telemetrytags.go create mode 100644 internal/pkg/postgresGorm/constants/constants.go create mode 100644 internal/pkg/postgresGorm/contracts/gorm_context.go rename internal/pkg/{gorm_postgres => postgresGorm}/db.go (56%) rename internal/pkg/{gorm_postgres => postgresGorm}/gorm_options.go (90%) rename internal/pkg/{gorm_postgres => postgresGorm}/gorm_options_test.go (87%) rename internal/pkg/{gorm_postgres => postgresGorm}/gorm_postgres_fx.go (95%) rename internal/pkg/{gorm_postgres => postgresGorm}/health.go (95%) rename internal/pkg/{gorm_postgres => postgresGorm}/helpers.go (57%) create mode 100644 internal/pkg/postgresGorm/helpers/helpers.go create mode 100644 internal/pkg/postgresGorm/mediatr/pipelines/mediator_transaction_pipeline.go rename internal/pkg/{gorm_postgres => postgresGorm}/repository/gorm_generic_repository.go (69%) create mode 100644 internal/pkg/postgresGorm/repository/gorm_generic_repository_test.go create mode 100644 internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go create mode 100644 internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository.go rename internal/pkg/{postgres_pgx => postgrespgx}/interface.go (100%) rename internal/pkg/{postgres_pgx => postgrespgx}/postgres.go (100%) rename internal/pkg/{postgres_pgx => postgrespgx}/postgres_pgx_fx.go (100%) rename internal/pkg/{postgres_pgx => postgrespgx}/postgres_pgx_options.go (95%) rename internal/pkg/{postgres_sqlx => postgressqlx}/postgres.go (100%) rename internal/pkg/{postgres_sqlx => postgressqlx}/postgres_sqlx_fx.go (100%) rename internal/pkg/{postgres_sqlx => postgressqlx}/postgres_sqlx_options.go (95%) rename internal/pkg/reflection/{reflection_helper => reflectionhelper}/reflection_helper.go (100%) rename internal/pkg/reflection/{reflection_helper => reflectionhelper}/reflection_helper_test.go (100%) rename internal/pkg/reflection/{type_mappper => typemapper}/type_mapper.go (97%) rename internal/pkg/reflection/{type_mappper => typemapper}/type_mapper_test.go (100%) rename internal/pkg/reflection/{type_mappper => typemapper}/unsafe_types.go (100%) rename internal/pkg/reflection/{type_registry => typeregistry}/type_registry.go (95%) rename internal/services/catalog_read_service/internal/shared/{test_fixture => testfixture}/integration/integration_test_fixture.go (96%) delete mode 100644 internal/services/catalog_write_service/internal/products/contracts/catalog_unit_of_work.go delete mode 100644 internal/services/catalog_write_service/internal/products/contracts/catalogs_context.go create mode 100644 internal/services/catalog_write_service/internal/products/data/models/product_data_model.go delete mode 100644 internal/services/catalog_write_service/internal/products/data/uow/catalog_context.go delete mode 100644 internal/services/catalog_write_service/internal/products/data/uow/catalogs_unit_of_work.go rename internal/services/catalog_write_service/internal/products/features/{deleting_product => deletingproduct}/v1/delete_product.go (82%) rename internal/services/catalog_write_service/internal/products/features/{deleting_product => deletingproduct}/v1/delete_product_endpoint.go (95%) rename internal/services/catalog_write_service/internal/products/features/{deleting_product => deletingproduct}/v1/delete_product_handler.go (50%) rename internal/services/catalog_write_service/internal/products/features/{deleting_product => deletingproduct}/v1/dtos/delete_product_request_dto.go (100%) rename internal/services/catalog_write_service/internal/products/features/{deleting_product => deletingproduct}/v1/events/integrationevents/product_deleted.go (94%) rename internal/services/catalog_write_service/internal/products/features/{getting_product_by_id => gettingproductbyid}/v1/dtos/get_product_by_id_request_dto.go (100%) rename internal/services/catalog_write_service/internal/products/features/{getting_product_by_id => gettingproductbyid}/v1/dtos/get_product_by_id_response_dto.go (100%) rename internal/services/catalog_write_service/internal/products/features/{getting_product_by_id => gettingproductbyid}/v1/get_product_by_id.go (100%) rename internal/services/catalog_write_service/internal/products/features/{getting_product_by_id => gettingproductbyid}/v1/get_product_by_id_endpoint.go (95%) rename internal/services/catalog_write_service/internal/products/features/{getting_product_by_id => gettingproductbyid}/v1/get_product_by_id_handler.go (74%) rename internal/services/catalog_write_service/internal/products/features/{searching_product => searchingproduct}/v1/dtos/search_products_request_dto.go (100%) rename internal/services/catalog_write_service/internal/products/features/{searching_product => searchingproduct}/v1/dtos/search_products_response_dto.go (100%) rename internal/services/catalog_write_service/internal/products/features/{searching_product => searchingproduct}/v1/search_products.go (100%) rename internal/services/catalog_write_service/internal/products/features/{searching_product => searchingproduct}/v1/search_products_endpoint.go (96%) rename internal/services/catalog_write_service/internal/products/features/{searching_product => searchingproduct}/v1/search_products_handler.go (56%) delete mode 100644 internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product_handler.go rename internal/services/catalog_write_service/internal/products/features/{updating_product => updatingproduct}/v1/dtos/update_product_request_dto.go (100%) rename internal/services/catalog_write_service/internal/products/features/{updating_product => updatingproduct}/v1/events/integrationevents/product_updated.go (95%) rename internal/services/catalog_write_service/internal/products/features/{updating_product => updatingproduct}/v1/update_product.go (50%) rename internal/services/catalog_write_service/internal/products/features/{updating_product => updatingproduct}/v1/update_product_endpoint.go (96%) create mode 100644 internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_handler.go delete mode 100644 internal/services/catalog_write_service/internal/products/mocks/testData/products.go create mode 100644 internal/services/catalog_write_service/internal/shared/data/data_fx.go create mode 100644 internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext.go create mode 100644 internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext_test.go delete mode 100644 internal/services/catalog_write_service/internal/shared/test_fixtures/unit_test/unit_test_fixture.go rename internal/services/catalog_write_service/internal/shared/{test_fixtures => testfixtures}/integration/integration_test_fixture.go (85%) create mode 100644 internal/services/catalog_write_service/internal/shared/testfixtures/unittest/unit_test_fixture.go delete mode 100644 internal/services/catalog_write_service/mocks/CatalogUnitOfWork.go delete mode 100644 internal/services/catalog_write_service/mocks/CatalogUnitOfWorkActionFunc.go rename internal/services/catalog_write_service/test/{end_to_end/products/features/creating_product => endtoend/products/features/creatingproduct}/v1/create_product_test.go (94%) rename internal/services/catalog_write_service/test/{end_to_end/products/features/deleting_product => endtoend/products/features/deletingproduct}/v1/delete_product_test.go (93%) rename internal/services/catalog_write_service/test/{end_to_end/products/features/getting_product_by_id => endtoend/products/features/gettingproductbyid}/v1/get_product_by_id_test.go (93%) rename internal/services/catalog_write_service/test/{end_to_end/products/features/getting_products => endtoend/products/features/gettingproducts}/v1/get_products_test.go (89%) rename internal/services/catalog_write_service/test/{end_to_end/products/features/searching_product => endtoend/products/features/searchingproduct}/v1/search_products_test.go (90%) rename internal/services/catalog_write_service/test/{end_to_end/products/features/updating_product => endtoend/products/features/updatingproduct}/v1/update_product_test.go (92%) rename internal/services/catalog_write_service/test/{end_to_end => endtoend}/products/grpc/product_grpc_service_server_test.go (94%) delete mode 100644 internal/services/catalog_write_service/test/integration/products/features/creating_product/v1/create_product_test.go create mode 100644 internal/services/catalog_write_service/test/integration/products/features/creatingproduct/v1/create_product_test.go rename internal/services/catalog_write_service/test/integration/products/features/{deleting_product => deletingproduct}/v1/delete_product_test.go (52%) delete mode 100644 internal/services/catalog_write_service/test/integration/products/features/getting_product_by_id/v1/get_product_by_id_test.go create mode 100644 internal/services/catalog_write_service/test/integration/products/features/gettingproductbyid/v1/get_product_by_id_test.go rename internal/services/catalog_write_service/test/integration/products/features/{getting_products => gettingproducts}/v1/get_products_test.go (77%) rename internal/services/catalog_write_service/test/integration/products/features/{updating_product => updatingproduct}/v1/update_product_test.go (56%) delete mode 100644 internal/services/catalog_write_service/test/unit/products/features/creating_product/v1/commands/create_product_handler_unit_test.go create mode 100644 internal/services/catalog_write_service/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go rename internal/services/catalog_write_service/test/unit/products/features/{creating_product/v1/commands => creatingproduct/v1}/create_product_unit_test.go (72%) delete mode 100644 internal/services/catalog_write_service/test/unit/products/features/deleting_product/v1/commands/delete_product_handler_unit_test.go create mode 100644 internal/services/catalog_write_service/test/unit/products/features/deletingproduct/v1/delete_product_handler_unit_test.go rename internal/services/catalog_write_service/test/unit/products/features/{deleting_product/v1/commands => deletingproduct/v1}/delete_product_unit_test.go (80%) delete mode 100644 internal/services/catalog_write_service/test/unit/products/features/getting_product_by_id/v1/queries/get_product_by_id_handler_unit_test.go delete mode 100644 internal/services/catalog_write_service/test/unit/products/features/getting_products/v1/queries/get_products_handler_unit_test.go rename internal/services/catalog_write_service/test/unit/products/features/{getting_product_by_id/v1/queries => gettingproductbyid/v1}/get_product_by_Id_unit_test.go (79%) create mode 100644 internal/services/catalog_write_service/test/unit/products/features/gettingproductbyid/v1/get_product_by_id_handler_unit_test.go create mode 100644 internal/services/catalog_write_service/test/unit/products/features/gettingproducts/v1/get_products_handler_unit_test.go create mode 100644 internal/services/catalog_write_service/test/unit/products/features/searchingproducts/v1/search_products_unit_test.go delete mode 100644 internal/services/catalog_write_service/test/unit/products/features/updating_product/v1/commands/update_product_handler_unit_test.go create mode 100644 internal/services/catalog_write_service/test/unit/products/features/updatingproduct/v1/update_product_handler_unit_test.go rename internal/services/catalog_write_service/test/unit/products/features/{updating_product/v1/commands => updatingproduct/v1}/update_product_unit_test.go (88%) diff --git a/internal/pkg/config/config_helper.go b/internal/pkg/config/config_helper.go index c96d56f0..968b1415 100644 --- a/internal/pkg/config/config_helper.go +++ b/internal/pkg/config/config_helper.go @@ -8,7 +8,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/constants" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "emperror.dev/errors" "github.com/caarlos0/env/v8" diff --git a/internal/pkg/config/environment/environment.go b/internal/pkg/config/environment/environment.go index 1e370bfa..7887fc35 100644 --- a/internal/pkg/config/environment/environment.go +++ b/internal/pkg/config/environment/environment.go @@ -42,6 +42,8 @@ func ConfigAppEnv(environments ...Environment) Environment { setRootWorkingDirectoryEnvironment() + fixTestEnvironmentWorkingDirectory() + manualEnv := os.Getenv(constants.AppEnv) if manualEnv != "" { @@ -59,6 +61,10 @@ func (env Environment) IsProduction() bool { return env == Production } +func (env Environment) IsTest() bool { + return env == Test +} + func (env Environment) GetEnvironmentName() string { return string(env) } @@ -67,6 +73,7 @@ func EnvString(key, fallback string) string { if value, ok := syscall.Getenv(key); ok { return value } + return fallback } @@ -123,6 +130,19 @@ func setRootWorkingDirectoryEnvironment() { viper.Set(constants.AppRootPath, absoluteRootWorkingDirectory) } +func fixTestEnvironmentWorkingDirectory() { + currentWD, _ := os.Getwd() + log.Printf("Current test working directory is: %s", currentWD) + + rootDir := viper.GetString(constants.AppRootPath) + if rootDir != "" { + _ = os.Chdir(rootDir) + + newWD, _ := os.Getwd() + log.Printf("New test working directory is: %s", newWD) + } +} + func getRootDirectoryFromProjectName(pn string) string { // set root working directory of our app in the viper // https://stackoverflow.com/a/47785436/581476 diff --git a/internal/pkg/core/cqrs/tx_request.go b/internal/pkg/core/cqrs/tx_request.go new file mode 100644 index 00000000..86f880bb --- /dev/null +++ b/internal/pkg/core/cqrs/tx_request.go @@ -0,0 +1,6 @@ +package cqrs + +// https://www.mohitkhare.com/blog/go-naming-conventions/ +type ITxRequest interface { + IsTxRequest() bool +} diff --git a/internal/pkg/core/custom_types/custom_time.go b/internal/pkg/core/customtypes/custom_time.go similarity index 100% rename from internal/pkg/core/custom_types/custom_time.go rename to internal/pkg/core/customtypes/custom_time.go diff --git a/internal/pkg/core/messaging/bus/bus.go b/internal/pkg/core/messaging/bus/bus.go new file mode 100644 index 00000000..1539fd36 --- /dev/null +++ b/internal/pkg/core/messaging/bus/bus.go @@ -0,0 +1,12 @@ +package bus + +import ( + consumer2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/producer" +) + +type Bus interface { + producer.Producer + consumer2.BusControl + consumer2.ConsumerConnector +} diff --git a/internal/pkg/messaging/consumer/consumer.go b/internal/pkg/core/messaging/consumer/consumer.go similarity index 92% rename from internal/pkg/messaging/consumer/consumer.go rename to internal/pkg/core/messaging/consumer/consumer.go index 22ca37d1..94cfde4f 100644 --- a/internal/pkg/messaging/consumer/consumer.go +++ b/internal/pkg/core/messaging/consumer/consumer.go @@ -3,7 +3,7 @@ package consumer import ( "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" ) type Consumer interface { diff --git a/internal/pkg/messaging/consumer/consumer_builder.go b/internal/pkg/core/messaging/consumer/consumer_builder.go similarity index 100% rename from internal/pkg/messaging/consumer/consumer_builder.go rename to internal/pkg/core/messaging/consumer/consumer_builder.go diff --git a/internal/pkg/messaging/consumer/consumer_connector.go b/internal/pkg/core/messaging/consumer/consumer_connector.go similarity index 95% rename from internal/pkg/messaging/consumer/consumer_connector.go rename to internal/pkg/core/messaging/consumer/consumer_connector.go index 289d6d31..e36f491c 100644 --- a/internal/pkg/messaging/consumer/consumer_connector.go +++ b/internal/pkg/core/messaging/consumer/consumer_connector.go @@ -1,7 +1,7 @@ package consumer import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" ) type ConsumerConnector interface { diff --git a/internal/pkg/messaging/consumer/consumer_handler.go b/internal/pkg/core/messaging/consumer/consumer_handler.go similarity index 90% rename from internal/pkg/messaging/consumer/consumer_handler.go rename to internal/pkg/core/messaging/consumer/consumer_handler.go index 677c527e..dc5b7ce2 100644 --- a/internal/pkg/messaging/consumer/consumer_handler.go +++ b/internal/pkg/core/messaging/consumer/consumer_handler.go @@ -3,7 +3,7 @@ package consumer import ( "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" ) type ConsumerHandler interface { diff --git a/internal/pkg/messaging/consumer/consumer_handler_configuration.go b/internal/pkg/core/messaging/consumer/consumer_handler_configuration.go similarity index 100% rename from internal/pkg/messaging/consumer/consumer_handler_configuration.go rename to internal/pkg/core/messaging/consumer/consumer_handler_configuration.go diff --git a/internal/pkg/messaging/consumer/consumer_handler_configuration_builder.go b/internal/pkg/core/messaging/consumer/consumer_handler_configuration_builder.go similarity index 100% rename from internal/pkg/messaging/consumer/consumer_handler_configuration_builder.go rename to internal/pkg/core/messaging/consumer/consumer_handler_configuration_builder.go diff --git a/internal/pkg/messaging/consumer/consumer_options.go b/internal/pkg/core/messaging/consumer/consumer_options.go similarity index 100% rename from internal/pkg/messaging/consumer/consumer_options.go rename to internal/pkg/core/messaging/consumer/consumer_options.go diff --git a/internal/pkg/messaging/consumer/consumers_control.go b/internal/pkg/core/messaging/consumer/consumers_control.go similarity index 92% rename from internal/pkg/messaging/consumer/consumers_control.go rename to internal/pkg/core/messaging/consumer/consumers_control.go index 2dff9c77..d539e1f7 100644 --- a/internal/pkg/messaging/consumer/consumers_control.go +++ b/internal/pkg/core/messaging/consumer/consumers_control.go @@ -3,7 +3,7 @@ package consumer import ( "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" ) type BusControl interface { diff --git a/internal/pkg/messaging/message_header/message_header.go b/internal/pkg/core/messaging/messageheader/message_header.go similarity index 100% rename from internal/pkg/messaging/message_header/message_header.go rename to internal/pkg/core/messaging/messageheader/message_header.go diff --git a/internal/pkg/messaging/message_header/metadata_message_extentions.go b/internal/pkg/core/messaging/messageheader/metadata_message_extentions.go similarity index 100% rename from internal/pkg/messaging/message_header/metadata_message_extentions.go rename to internal/pkg/core/messaging/messageheader/metadata_message_extentions.go diff --git a/internal/pkg/messaging/mocks/Bus.go b/internal/pkg/core/messaging/mocks/Bus.go similarity index 92% rename from internal/pkg/messaging/mocks/Bus.go rename to internal/pkg/core/messaging/mocks/Bus.go index 3e1bd32e..59b746e6 100644 --- a/internal/pkg/messaging/mocks/Bus.go +++ b/internal/pkg/core/messaging/mocks/Bus.go @@ -5,13 +5,11 @@ package mocks import ( context "context" - consumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - + consumer2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" metadata "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" mock "github.com/stretchr/testify/mock" - - types "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" ) // Bus is an autogenerated mock type for the Bus type @@ -94,11 +92,11 @@ func (_c *Bus_AddMessageProducedHandler_Call) RunAndReturn(run func(func(types.I } // ConnectConsumer provides a mock function with given fields: messageType, _a1 -func (_m *Bus) ConnectConsumer(messageType types.IMessage, _a1 consumer.Consumer) error { +func (_m *Bus) ConnectConsumer(messageType types.IMessage, _a1 consumer2.Consumer) error { ret := _m.Called(messageType, _a1) var r0 error - if rf, ok := ret.Get(0).(func(types.IMessage, consumer.Consumer) error); ok { + if rf, ok := ret.Get(0).(func(types.IMessage, consumer2.Consumer) error); ok { r0 = rf(messageType, _a1) } else { r0 = ret.Error(0) @@ -119,9 +117,9 @@ func (_e *Bus_Expecter) ConnectConsumer(messageType interface{}, _a1 interface{} return &Bus_ConnectConsumer_Call{Call: _e.mock.On("ConnectConsumer", messageType, _a1)} } -func (_c *Bus_ConnectConsumer_Call) Run(run func(messageType types.IMessage, _a1 consumer.Consumer)) *Bus_ConnectConsumer_Call { +func (_c *Bus_ConnectConsumer_Call) Run(run func(messageType types.IMessage, _a1 consumer2.Consumer)) *Bus_ConnectConsumer_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.IMessage), args[1].(consumer.Consumer)) + run(args[0].(types.IMessage), args[1].(consumer2.Consumer)) }) return _c } @@ -131,17 +129,17 @@ func (_c *Bus_ConnectConsumer_Call) Return(_a0 error) *Bus_ConnectConsumer_Call return _c } -func (_c *Bus_ConnectConsumer_Call) RunAndReturn(run func(types.IMessage, consumer.Consumer) error) *Bus_ConnectConsumer_Call { +func (_c *Bus_ConnectConsumer_Call) RunAndReturn(run func(types.IMessage, consumer2.Consumer) error) *Bus_ConnectConsumer_Call { _c.Call.Return(run) return _c } // ConnectConsumerHandler provides a mock function with given fields: messageType, consumerHandler -func (_m *Bus) ConnectConsumerHandler(messageType types.IMessage, consumerHandler consumer.ConsumerHandler) error { +func (_m *Bus) ConnectConsumerHandler(messageType types.IMessage, consumerHandler consumer2.ConsumerHandler) error { ret := _m.Called(messageType, consumerHandler) var r0 error - if rf, ok := ret.Get(0).(func(types.IMessage, consumer.ConsumerHandler) error); ok { + if rf, ok := ret.Get(0).(func(types.IMessage, consumer2.ConsumerHandler) error); ok { r0 = rf(messageType, consumerHandler) } else { r0 = ret.Error(0) @@ -162,9 +160,9 @@ func (_e *Bus_Expecter) ConnectConsumerHandler(messageType interface{}, consumer return &Bus_ConnectConsumerHandler_Call{Call: _e.mock.On("ConnectConsumerHandler", messageType, consumerHandler)} } -func (_c *Bus_ConnectConsumerHandler_Call) Run(run func(messageType types.IMessage, consumerHandler consumer.ConsumerHandler)) *Bus_ConnectConsumerHandler_Call { +func (_c *Bus_ConnectConsumerHandler_Call) Run(run func(messageType types.IMessage, consumerHandler consumer2.ConsumerHandler)) *Bus_ConnectConsumerHandler_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.IMessage), args[1].(consumer.ConsumerHandler)) + run(args[0].(types.IMessage), args[1].(consumer2.ConsumerHandler)) }) return _c } @@ -174,7 +172,7 @@ func (_c *Bus_ConnectConsumerHandler_Call) Return(_a0 error) *Bus_ConnectConsume return _c } -func (_c *Bus_ConnectConsumerHandler_Call) RunAndReturn(run func(types.IMessage, consumer.ConsumerHandler) error) *Bus_ConnectConsumerHandler_Call { +func (_c *Bus_ConnectConsumerHandler_Call) RunAndReturn(run func(types.IMessage, consumer2.ConsumerHandler) error) *Bus_ConnectConsumerHandler_Call { _c.Call.Return(run) return _c } @@ -356,7 +354,8 @@ func (_c *Bus_Stop_Call) RunAndReturn(run func() error) *Bus_Stop_Call { func NewBus(t interface { mock.TestingT Cleanup(func()) -}) *Bus { +}, +) *Bus { mock := &Bus{} mock.Mock.Test(t) diff --git a/internal/pkg/messaging/mocks/BusControl.go b/internal/pkg/core/messaging/mocks/BusControl.go similarity index 97% rename from internal/pkg/messaging/mocks/BusControl.go rename to internal/pkg/core/messaging/mocks/BusControl.go index cbe10475..bbd1337e 100644 --- a/internal/pkg/messaging/mocks/BusControl.go +++ b/internal/pkg/core/messaging/mocks/BusControl.go @@ -5,7 +5,8 @@ package mocks import ( context "context" - types "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" + mock "github.com/stretchr/testify/mock" ) @@ -143,7 +144,8 @@ func (_c *BusControl_Stop_Call) RunAndReturn(run func() error) *BusControl_Stop_ func NewBusControl(t interface { mock.TestingT Cleanup(func()) -}) *BusControl { +}, +) *BusControl { mock := &BusControl{} mock.Mock.Test(t) diff --git a/internal/pkg/messaging/mocks/Consumer.go b/internal/pkg/core/messaging/mocks/Consumer.go similarity index 96% rename from internal/pkg/messaging/mocks/Consumer.go rename to internal/pkg/core/messaging/mocks/Consumer.go index 2f4c8243..e076757a 100644 --- a/internal/pkg/messaging/mocks/Consumer.go +++ b/internal/pkg/core/messaging/mocks/Consumer.go @@ -5,11 +5,10 @@ package mocks import ( context "context" - consumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" mock "github.com/stretchr/testify/mock" - - types "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" ) // Consumer is an autogenerated mock type for the Consumer type @@ -179,7 +178,8 @@ func (_c *Consumer_Stop_Call) RunAndReturn(run func() error) *Consumer_Stop_Call func NewConsumer(t interface { mock.TestingT Cleanup(func()) -}) *Consumer { +}, +) *Consumer { mock := &Consumer{} mock.Mock.Test(t) diff --git a/internal/pkg/messaging/mocks/ConsumerBuilderFucT.go b/internal/pkg/core/messaging/mocks/ConsumerBuilderFucT.go similarity index 100% rename from internal/pkg/messaging/mocks/ConsumerBuilderFucT.go rename to internal/pkg/core/messaging/mocks/ConsumerBuilderFucT.go diff --git a/internal/pkg/messaging/mocks/ConsumerConnector.go b/internal/pkg/core/messaging/mocks/ConsumerConnector.go similarity index 77% rename from internal/pkg/messaging/mocks/ConsumerConnector.go rename to internal/pkg/core/messaging/mocks/ConsumerConnector.go index edd3e55d..5746d453 100644 --- a/internal/pkg/messaging/mocks/ConsumerConnector.go +++ b/internal/pkg/core/messaging/mocks/ConsumerConnector.go @@ -3,10 +3,10 @@ package mocks import ( - consumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - mock "github.com/stretchr/testify/mock" + consumer2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" - types "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + mock "github.com/stretchr/testify/mock" ) // ConsumerConnector is an autogenerated mock type for the ConsumerConnector type @@ -23,11 +23,11 @@ func (_m *ConsumerConnector) EXPECT() *ConsumerConnector_Expecter { } // ConnectConsumer provides a mock function with given fields: messageType, _a1 -func (_m *ConsumerConnector) ConnectConsumer(messageType types.IMessage, _a1 consumer.Consumer) error { +func (_m *ConsumerConnector) ConnectConsumer(messageType types.IMessage, _a1 consumer2.Consumer) error { ret := _m.Called(messageType, _a1) var r0 error - if rf, ok := ret.Get(0).(func(types.IMessage, consumer.Consumer) error); ok { + if rf, ok := ret.Get(0).(func(types.IMessage, consumer2.Consumer) error); ok { r0 = rf(messageType, _a1) } else { r0 = ret.Error(0) @@ -48,9 +48,9 @@ func (_e *ConsumerConnector_Expecter) ConnectConsumer(messageType interface{}, _ return &ConsumerConnector_ConnectConsumer_Call{Call: _e.mock.On("ConnectConsumer", messageType, _a1)} } -func (_c *ConsumerConnector_ConnectConsumer_Call) Run(run func(messageType types.IMessage, _a1 consumer.Consumer)) *ConsumerConnector_ConnectConsumer_Call { +func (_c *ConsumerConnector_ConnectConsumer_Call) Run(run func(messageType types.IMessage, _a1 consumer2.Consumer)) *ConsumerConnector_ConnectConsumer_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.IMessage), args[1].(consumer.Consumer)) + run(args[0].(types.IMessage), args[1].(consumer2.Consumer)) }) return _c } @@ -60,17 +60,17 @@ func (_c *ConsumerConnector_ConnectConsumer_Call) Return(_a0 error) *ConsumerCon return _c } -func (_c *ConsumerConnector_ConnectConsumer_Call) RunAndReturn(run func(types.IMessage, consumer.Consumer) error) *ConsumerConnector_ConnectConsumer_Call { +func (_c *ConsumerConnector_ConnectConsumer_Call) RunAndReturn(run func(types.IMessage, consumer2.Consumer) error) *ConsumerConnector_ConnectConsumer_Call { _c.Call.Return(run) return _c } // ConnectConsumerHandler provides a mock function with given fields: messageType, consumerHandler -func (_m *ConsumerConnector) ConnectConsumerHandler(messageType types.IMessage, consumerHandler consumer.ConsumerHandler) error { +func (_m *ConsumerConnector) ConnectConsumerHandler(messageType types.IMessage, consumerHandler consumer2.ConsumerHandler) error { ret := _m.Called(messageType, consumerHandler) var r0 error - if rf, ok := ret.Get(0).(func(types.IMessage, consumer.ConsumerHandler) error); ok { + if rf, ok := ret.Get(0).(func(types.IMessage, consumer2.ConsumerHandler) error); ok { r0 = rf(messageType, consumerHandler) } else { r0 = ret.Error(0) @@ -91,9 +91,9 @@ func (_e *ConsumerConnector_Expecter) ConnectConsumerHandler(messageType interfa return &ConsumerConnector_ConnectConsumerHandler_Call{Call: _e.mock.On("ConnectConsumerHandler", messageType, consumerHandler)} } -func (_c *ConsumerConnector_ConnectConsumerHandler_Call) Run(run func(messageType types.IMessage, consumerHandler consumer.ConsumerHandler)) *ConsumerConnector_ConnectConsumerHandler_Call { +func (_c *ConsumerConnector_ConnectConsumerHandler_Call) Run(run func(messageType types.IMessage, consumerHandler consumer2.ConsumerHandler)) *ConsumerConnector_ConnectConsumerHandler_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.IMessage), args[1].(consumer.ConsumerHandler)) + run(args[0].(types.IMessage), args[1].(consumer2.ConsumerHandler)) }) return _c } @@ -103,7 +103,7 @@ func (_c *ConsumerConnector_ConnectConsumerHandler_Call) Return(_a0 error) *Cons return _c } -func (_c *ConsumerConnector_ConnectConsumerHandler_Call) RunAndReturn(run func(types.IMessage, consumer.ConsumerHandler) error) *ConsumerConnector_ConnectConsumerHandler_Call { +func (_c *ConsumerConnector_ConnectConsumerHandler_Call) RunAndReturn(run func(types.IMessage, consumer2.ConsumerHandler) error) *ConsumerConnector_ConnectConsumerHandler_Call { _c.Call.Return(run) return _c } @@ -113,7 +113,8 @@ func (_c *ConsumerConnector_ConnectConsumerHandler_Call) RunAndReturn(run func(t func NewConsumerConnector(t interface { mock.TestingT Cleanup(func()) -}) *ConsumerConnector { +}, +) *ConsumerConnector { mock := &ConsumerConnector{} mock.Mock.Test(t) diff --git a/internal/pkg/messaging/mocks/ConsumerHandler.go b/internal/pkg/core/messaging/mocks/ConsumerHandler.go similarity index 95% rename from internal/pkg/messaging/mocks/ConsumerHandler.go rename to internal/pkg/core/messaging/mocks/ConsumerHandler.go index 279c5696..489023f5 100644 --- a/internal/pkg/messaging/mocks/ConsumerHandler.go +++ b/internal/pkg/core/messaging/mocks/ConsumerHandler.go @@ -5,7 +5,8 @@ package mocks import ( context "context" - types "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" + mock "github.com/stretchr/testify/mock" ) @@ -70,7 +71,8 @@ func (_c *ConsumerHandler_Handle_Call) RunAndReturn(run func(context.Context, ty func NewConsumerHandler(t interface { mock.TestingT Cleanup(func()) -}) *ConsumerHandler { +}, +) *ConsumerHandler { mock := &ConsumerHandler{} mock.Mock.Test(t) diff --git a/internal/pkg/messaging/mocks/ConsumerHandlerConfigurationBuilder.go b/internal/pkg/core/messaging/mocks/ConsumerHandlerConfigurationBuilder.go similarity index 71% rename from internal/pkg/messaging/mocks/ConsumerHandlerConfigurationBuilder.go rename to internal/pkg/core/messaging/mocks/ConsumerHandlerConfigurationBuilder.go index 3cf46da4..938b022b 100644 --- a/internal/pkg/messaging/mocks/ConsumerHandlerConfigurationBuilder.go +++ b/internal/pkg/core/messaging/mocks/ConsumerHandlerConfigurationBuilder.go @@ -3,7 +3,8 @@ package mocks import ( - consumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" + consumer2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + mock "github.com/stretchr/testify/mock" ) @@ -21,15 +22,15 @@ func (_m *ConsumerHandlerConfigurationBuilder) EXPECT() *ConsumerHandlerConfigur } // AddHandler provides a mock function with given fields: handler -func (_m *ConsumerHandlerConfigurationBuilder) AddHandler(handler consumer.ConsumerHandler) consumer.ConsumerHandlerConfigurationBuilder { +func (_m *ConsumerHandlerConfigurationBuilder) AddHandler(handler consumer2.ConsumerHandler) consumer2.ConsumerHandlerConfigurationBuilder { ret := _m.Called(handler) - var r0 consumer.ConsumerHandlerConfigurationBuilder - if rf, ok := ret.Get(0).(func(consumer.ConsumerHandler) consumer.ConsumerHandlerConfigurationBuilder); ok { + var r0 consumer2.ConsumerHandlerConfigurationBuilder + if rf, ok := ret.Get(0).(func(consumer2.ConsumerHandler) consumer2.ConsumerHandlerConfigurationBuilder); ok { r0 = rf(handler) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(consumer.ConsumerHandlerConfigurationBuilder) + r0 = ret.Get(0).(consumer2.ConsumerHandlerConfigurationBuilder) } } @@ -47,33 +48,33 @@ func (_e *ConsumerHandlerConfigurationBuilder_Expecter) AddHandler(handler inter return &ConsumerHandlerConfigurationBuilder_AddHandler_Call{Call: _e.mock.On("AddHandler", handler)} } -func (_c *ConsumerHandlerConfigurationBuilder_AddHandler_Call) Run(run func(handler consumer.ConsumerHandler)) *ConsumerHandlerConfigurationBuilder_AddHandler_Call { +func (_c *ConsumerHandlerConfigurationBuilder_AddHandler_Call) Run(run func(handler consumer2.ConsumerHandler)) *ConsumerHandlerConfigurationBuilder_AddHandler_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(consumer.ConsumerHandler)) + run(args[0].(consumer2.ConsumerHandler)) }) return _c } -func (_c *ConsumerHandlerConfigurationBuilder_AddHandler_Call) Return(_a0 consumer.ConsumerHandlerConfigurationBuilder) *ConsumerHandlerConfigurationBuilder_AddHandler_Call { +func (_c *ConsumerHandlerConfigurationBuilder_AddHandler_Call) Return(_a0 consumer2.ConsumerHandlerConfigurationBuilder) *ConsumerHandlerConfigurationBuilder_AddHandler_Call { _c.Call.Return(_a0) return _c } -func (_c *ConsumerHandlerConfigurationBuilder_AddHandler_Call) RunAndReturn(run func(consumer.ConsumerHandler) consumer.ConsumerHandlerConfigurationBuilder) *ConsumerHandlerConfigurationBuilder_AddHandler_Call { +func (_c *ConsumerHandlerConfigurationBuilder_AddHandler_Call) RunAndReturn(run func(consumer2.ConsumerHandler) consumer2.ConsumerHandlerConfigurationBuilder) *ConsumerHandlerConfigurationBuilder_AddHandler_Call { _c.Call.Return(run) return _c } // Build provides a mock function with given fields: -func (_m *ConsumerHandlerConfigurationBuilder) Build() *consumer.ConsumerHandlersConfiguration { +func (_m *ConsumerHandlerConfigurationBuilder) Build() *consumer2.ConsumerHandlersConfiguration { ret := _m.Called() - var r0 *consumer.ConsumerHandlersConfiguration - if rf, ok := ret.Get(0).(func() *consumer.ConsumerHandlersConfiguration); ok { + var r0 *consumer2.ConsumerHandlersConfiguration + if rf, ok := ret.Get(0).(func() *consumer2.ConsumerHandlersConfiguration); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*consumer.ConsumerHandlersConfiguration) + r0 = ret.Get(0).(*consumer2.ConsumerHandlersConfiguration) } } @@ -97,12 +98,12 @@ func (_c *ConsumerHandlerConfigurationBuilder_Build_Call) Run(run func()) *Consu return _c } -func (_c *ConsumerHandlerConfigurationBuilder_Build_Call) Return(_a0 *consumer.ConsumerHandlersConfiguration) *ConsumerHandlerConfigurationBuilder_Build_Call { +func (_c *ConsumerHandlerConfigurationBuilder_Build_Call) Return(_a0 *consumer2.ConsumerHandlersConfiguration) *ConsumerHandlerConfigurationBuilder_Build_Call { _c.Call.Return(_a0) return _c } -func (_c *ConsumerHandlerConfigurationBuilder_Build_Call) RunAndReturn(run func() *consumer.ConsumerHandlersConfiguration) *ConsumerHandlerConfigurationBuilder_Build_Call { +func (_c *ConsumerHandlerConfigurationBuilder_Build_Call) RunAndReturn(run func() *consumer2.ConsumerHandlersConfiguration) *ConsumerHandlerConfigurationBuilder_Build_Call { _c.Call.Return(run) return _c } @@ -112,7 +113,8 @@ func (_c *ConsumerHandlerConfigurationBuilder_Build_Call) RunAndReturn(run func( func NewConsumerHandlerConfigurationBuilder(t interface { mock.TestingT Cleanup(func()) -}) *ConsumerHandlerConfigurationBuilder { +}, +) *ConsumerHandlerConfigurationBuilder { mock := &ConsumerHandlerConfigurationBuilder{} mock.Mock.Test(t) diff --git a/internal/pkg/messaging/mocks/ConsumerHandlerConfigurationBuilderFunc.go b/internal/pkg/core/messaging/mocks/ConsumerHandlerConfigurationBuilderFunc.go similarity index 94% rename from internal/pkg/messaging/mocks/ConsumerHandlerConfigurationBuilderFunc.go rename to internal/pkg/core/messaging/mocks/ConsumerHandlerConfigurationBuilderFunc.go index 9addc220..86a40be7 100644 --- a/internal/pkg/messaging/mocks/ConsumerHandlerConfigurationBuilderFunc.go +++ b/internal/pkg/core/messaging/mocks/ConsumerHandlerConfigurationBuilderFunc.go @@ -3,7 +3,8 @@ package mocks import ( - consumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + mock "github.com/stretchr/testify/mock" ) @@ -58,7 +59,8 @@ func (_c *ConsumerHandlerConfigurationBuilderFunc_Execute_Call) RunAndReturn(run func NewConsumerHandlerConfigurationBuilderFunc(t interface { mock.TestingT Cleanup(func()) -}) *ConsumerHandlerConfigurationBuilderFunc { +}, +) *ConsumerHandlerConfigurationBuilderFunc { mock := &ConsumerHandlerConfigurationBuilderFunc{} mock.Mock.Test(t) diff --git a/internal/pkg/messaging/mocks/ConsumerHandlerFunc.go b/internal/pkg/core/messaging/mocks/ConsumerHandlerFunc.go similarity index 100% rename from internal/pkg/messaging/mocks/ConsumerHandlerFunc.go rename to internal/pkg/core/messaging/mocks/ConsumerHandlerFunc.go diff --git a/internal/pkg/messaging/mocks/ConsumerPipeline.go b/internal/pkg/core/messaging/mocks/ConsumerPipeline.go similarity index 92% rename from internal/pkg/messaging/mocks/ConsumerPipeline.go rename to internal/pkg/core/messaging/mocks/ConsumerPipeline.go index 9484d083..bd884afe 100644 --- a/internal/pkg/messaging/mocks/ConsumerPipeline.go +++ b/internal/pkg/core/messaging/mocks/ConsumerPipeline.go @@ -5,8 +5,9 @@ package mocks import ( context "context" - pipeline "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/pipeline" - types "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/pipeline" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" + mock "github.com/stretchr/testify/mock" ) @@ -72,7 +73,8 @@ func (_c *ConsumerPipeline_Handle_Call) RunAndReturn(run func(context.Context, t func NewConsumerPipeline(t interface { mock.TestingT Cleanup(func()) -}) *ConsumerPipeline { +}, +) *ConsumerPipeline { mock := &ConsumerPipeline{} mock.Mock.Test(t) diff --git a/internal/pkg/messaging/mocks/ConsumerPipelineConfigurationBuilder.go b/internal/pkg/core/messaging/mocks/ConsumerPipelineConfigurationBuilder.go similarity index 72% rename from internal/pkg/messaging/mocks/ConsumerPipelineConfigurationBuilder.go rename to internal/pkg/core/messaging/mocks/ConsumerPipelineConfigurationBuilder.go index f9134409..9e52fcaf 100644 --- a/internal/pkg/messaging/mocks/ConsumerPipelineConfigurationBuilder.go +++ b/internal/pkg/core/messaging/mocks/ConsumerPipelineConfigurationBuilder.go @@ -3,7 +3,8 @@ package mocks import ( - pipeline "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/pipeline" + pipeline2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/pipeline" + mock "github.com/stretchr/testify/mock" ) @@ -21,15 +22,15 @@ func (_m *ConsumerPipelineConfigurationBuilder) EXPECT() *ConsumerPipelineConfig } // AddPipeline provides a mock function with given fields: _a0 -func (_m *ConsumerPipelineConfigurationBuilder) AddPipeline(_a0 pipeline.ConsumerPipeline) pipeline.ConsumerPipelineConfigurationBuilder { +func (_m *ConsumerPipelineConfigurationBuilder) AddPipeline(_a0 pipeline2.ConsumerPipeline) pipeline2.ConsumerPipelineConfigurationBuilder { ret := _m.Called(_a0) - var r0 pipeline.ConsumerPipelineConfigurationBuilder - if rf, ok := ret.Get(0).(func(pipeline.ConsumerPipeline) pipeline.ConsumerPipelineConfigurationBuilder); ok { + var r0 pipeline2.ConsumerPipelineConfigurationBuilder + if rf, ok := ret.Get(0).(func(pipeline2.ConsumerPipeline) pipeline2.ConsumerPipelineConfigurationBuilder); ok { r0 = rf(_a0) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(pipeline.ConsumerPipelineConfigurationBuilder) + r0 = ret.Get(0).(pipeline2.ConsumerPipelineConfigurationBuilder) } } @@ -47,33 +48,33 @@ func (_e *ConsumerPipelineConfigurationBuilder_Expecter) AddPipeline(_a0 interfa return &ConsumerPipelineConfigurationBuilder_AddPipeline_Call{Call: _e.mock.On("AddPipeline", _a0)} } -func (_c *ConsumerPipelineConfigurationBuilder_AddPipeline_Call) Run(run func(_a0 pipeline.ConsumerPipeline)) *ConsumerPipelineConfigurationBuilder_AddPipeline_Call { +func (_c *ConsumerPipelineConfigurationBuilder_AddPipeline_Call) Run(run func(_a0 pipeline2.ConsumerPipeline)) *ConsumerPipelineConfigurationBuilder_AddPipeline_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(pipeline.ConsumerPipeline)) + run(args[0].(pipeline2.ConsumerPipeline)) }) return _c } -func (_c *ConsumerPipelineConfigurationBuilder_AddPipeline_Call) Return(_a0 pipeline.ConsumerPipelineConfigurationBuilder) *ConsumerPipelineConfigurationBuilder_AddPipeline_Call { +func (_c *ConsumerPipelineConfigurationBuilder_AddPipeline_Call) Return(_a0 pipeline2.ConsumerPipelineConfigurationBuilder) *ConsumerPipelineConfigurationBuilder_AddPipeline_Call { _c.Call.Return(_a0) return _c } -func (_c *ConsumerPipelineConfigurationBuilder_AddPipeline_Call) RunAndReturn(run func(pipeline.ConsumerPipeline) pipeline.ConsumerPipelineConfigurationBuilder) *ConsumerPipelineConfigurationBuilder_AddPipeline_Call { +func (_c *ConsumerPipelineConfigurationBuilder_AddPipeline_Call) RunAndReturn(run func(pipeline2.ConsumerPipeline) pipeline2.ConsumerPipelineConfigurationBuilder) *ConsumerPipelineConfigurationBuilder_AddPipeline_Call { _c.Call.Return(run) return _c } // Build provides a mock function with given fields: -func (_m *ConsumerPipelineConfigurationBuilder) Build() *pipeline.ConsumerPipelineConfiguration { +func (_m *ConsumerPipelineConfigurationBuilder) Build() *pipeline2.ConsumerPipelineConfiguration { ret := _m.Called() - var r0 *pipeline.ConsumerPipelineConfiguration - if rf, ok := ret.Get(0).(func() *pipeline.ConsumerPipelineConfiguration); ok { + var r0 *pipeline2.ConsumerPipelineConfiguration + if rf, ok := ret.Get(0).(func() *pipeline2.ConsumerPipelineConfiguration); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*pipeline.ConsumerPipelineConfiguration) + r0 = ret.Get(0).(*pipeline2.ConsumerPipelineConfiguration) } } @@ -97,12 +98,12 @@ func (_c *ConsumerPipelineConfigurationBuilder_Build_Call) Run(run func()) *Cons return _c } -func (_c *ConsumerPipelineConfigurationBuilder_Build_Call) Return(_a0 *pipeline.ConsumerPipelineConfiguration) *ConsumerPipelineConfigurationBuilder_Build_Call { +func (_c *ConsumerPipelineConfigurationBuilder_Build_Call) Return(_a0 *pipeline2.ConsumerPipelineConfiguration) *ConsumerPipelineConfigurationBuilder_Build_Call { _c.Call.Return(_a0) return _c } -func (_c *ConsumerPipelineConfigurationBuilder_Build_Call) RunAndReturn(run func() *pipeline.ConsumerPipelineConfiguration) *ConsumerPipelineConfigurationBuilder_Build_Call { +func (_c *ConsumerPipelineConfigurationBuilder_Build_Call) RunAndReturn(run func() *pipeline2.ConsumerPipelineConfiguration) *ConsumerPipelineConfigurationBuilder_Build_Call { _c.Call.Return(run) return _c } diff --git a/internal/pkg/messaging/mocks/ConsumerPipelineConfigurationBuilderFunc.go b/internal/pkg/core/messaging/mocks/ConsumerPipelineConfigurationBuilderFunc.go similarity index 94% rename from internal/pkg/messaging/mocks/ConsumerPipelineConfigurationBuilderFunc.go rename to internal/pkg/core/messaging/mocks/ConsumerPipelineConfigurationBuilderFunc.go index cc2c887b..c18b03bc 100644 --- a/internal/pkg/messaging/mocks/ConsumerPipelineConfigurationBuilderFunc.go +++ b/internal/pkg/core/messaging/mocks/ConsumerPipelineConfigurationBuilderFunc.go @@ -3,7 +3,8 @@ package mocks import ( - pipeline "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/pipeline" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/pipeline" + mock "github.com/stretchr/testify/mock" ) @@ -58,7 +59,8 @@ func (_c *ConsumerPipelineConfigurationBuilderFunc_Execute_Call) RunAndReturn(ru func NewConsumerPipelineConfigurationBuilderFunc(t interface { mock.TestingT Cleanup(func()) -}) *ConsumerPipelineConfigurationBuilderFunc { +}, +) *ConsumerPipelineConfigurationBuilderFunc { mock := &ConsumerPipelineConfigurationBuilderFunc{} mock.Mock.Test(t) diff --git a/internal/pkg/messaging/mocks/IMessage.go b/internal/pkg/core/messaging/mocks/IMessage.go similarity index 100% rename from internal/pkg/messaging/mocks/IMessage.go rename to internal/pkg/core/messaging/mocks/IMessage.go diff --git a/internal/pkg/messaging/mocks/MessageConsumeContext.go b/internal/pkg/core/messaging/mocks/MessageConsumeContext.go similarity index 98% rename from internal/pkg/messaging/mocks/MessageConsumeContext.go rename to internal/pkg/core/messaging/mocks/MessageConsumeContext.go index dce06413..fd21aec7 100644 --- a/internal/pkg/messaging/mocks/MessageConsumeContext.go +++ b/internal/pkg/core/messaging/mocks/MessageConsumeContext.go @@ -3,12 +3,12 @@ package mocks import ( - metadata "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" - mock "github.com/stretchr/testify/mock" - time "time" - types "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" + metadata "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" + + mock "github.com/stretchr/testify/mock" ) // MessageConsumeContext is an autogenerated mock type for the MessageConsumeContext type @@ -361,7 +361,8 @@ func (_c *MessageConsumeContext_Metadata_Call) RunAndReturn(run func() metadata. func NewMessageConsumeContext(t interface { mock.TestingT Cleanup(func()) -}) *MessageConsumeContext { +}, +) *MessageConsumeContext { mock := &MessageConsumeContext{} mock.Mock.Test(t) diff --git a/internal/pkg/messaging/mocks/Producer.go b/internal/pkg/core/messaging/mocks/Producer.go similarity index 98% rename from internal/pkg/messaging/mocks/Producer.go rename to internal/pkg/core/messaging/mocks/Producer.go index ea8b9614..4cf3b961 100644 --- a/internal/pkg/messaging/mocks/Producer.go +++ b/internal/pkg/core/messaging/mocks/Producer.go @@ -5,10 +5,10 @@ package mocks import ( context "context" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" metadata "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" - mock "github.com/stretchr/testify/mock" - types "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + mock "github.com/stretchr/testify/mock" ) // Producer is an autogenerated mock type for the Producer type @@ -151,7 +151,8 @@ func (_c *Producer_PublishMessageWithTopicName_Call) RunAndReturn(run func(conte func NewProducer(t interface { mock.TestingT Cleanup(func()) -}) *Producer { +}, +) *Producer { mock := &Producer{} mock.Mock.Test(t) diff --git a/internal/pkg/messaging/mocks/ProducerBuilderFuc.go b/internal/pkg/core/messaging/mocks/ProducerBuilderFuc.go similarity index 100% rename from internal/pkg/messaging/mocks/ProducerBuilderFuc.go rename to internal/pkg/core/messaging/mocks/ProducerBuilderFuc.go diff --git a/internal/pkg/messaging/otel/tracing/consts.go b/internal/pkg/core/messaging/otel/tracing/consts.go similarity index 100% rename from internal/pkg/messaging/otel/tracing/consts.go rename to internal/pkg/core/messaging/otel/tracing/consts.go diff --git a/internal/pkg/messaging/otel/tracing/consumer/consumer.go b/internal/pkg/core/messaging/otel/tracing/consumer/consumer.go similarity index 88% rename from internal/pkg/messaging/otel/tracing/consumer/consumer.go rename to internal/pkg/core/messaging/otel/tracing/consumer/consumer.go index 6452a03b..f41a2eda 100644 --- a/internal/pkg/messaging/otel/tracing/consumer/consumer.go +++ b/internal/pkg/core/messaging/otel/tracing/consumer/consumer.go @@ -5,9 +5,9 @@ import ( "fmt" "time" + messageHeader "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/messageheader" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" - messageHeader "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/message_header" - messageTracing "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants" tracingHeaders "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/tracing_headers" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" @@ -36,14 +36,14 @@ func StartConsumerSpan( // If there's a span context in the message, use that as the parent context. // extracts the tracing from the header and puts it into the context - carrier := messageTracing.NewMessageCarrier(meta) + carrier := tracing.NewMessageCarrier(meta) parentSpanContext := otel.GetTextMapPropagator().Extract(ctx, carrier) 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 - ctx, span := messageTracing.MessagingTracer.Start( + ctx, span := tracing.MessagingTracer.Start( parentSpanContext, fmt.Sprintf("%s %s", consumerTracingOptions.Destination, "receive"), opts...) @@ -58,7 +58,7 @@ func StartConsumerSpan( } func FinishConsumerSpan(span trace.Span, err error) error { - messageName := utils.GetSpanAttribute(span, messageTracing.MessageName).Value.AsString() + messageName := utils.GetSpanAttribute(span, tracing.MessageName).Value.AsString() if err != nil { span.AddEvent(fmt.Sprintf("failed to consume message '%s' from the broker", messageName)) @@ -92,10 +92,10 @@ func getTraceOptions( attribute.Key(constants.Traceparent).String(tracingHeaders.GetTracingTraceparent(*meta)), attribute.Key(constants.ParentSpanId).String(tracingHeaders.GetTracingParentSpanId(*meta)), attribute.Key(constants.Timestamp).Int64(time.Now().UnixMilli()), - attribute.Key(messageTracing.MessageType).String(messageHeader.GetMessageType(*meta)), - attribute.Key(messageTracing.MessageName).String(messageHeader.GetMessageName(*meta)), - attribute.Key(messageTracing.Payload).String(payload), - attribute.String(messageTracing.Headers, meta.ToJson()), + attribute.Key(tracing.MessageType).String(messageHeader.GetMessageType(*meta)), + attribute.Key(tracing.MessageName).String(messageHeader.GetMessageName(*meta)), + attribute.Key(tracing.Payload).String(payload), + attribute.String(tracing.Headers, meta.ToJson()), semconv.MessagingDestinationName(consumerTracingOptions.Destination), semconv.MessagingSystemKey.String(consumerTracingOptions.MessagingSystem), } diff --git a/internal/pkg/messaging/otel/tracing/consumer/consumer_tracing_options.go b/internal/pkg/core/messaging/otel/tracing/consumer/consumer_tracing_options.go similarity index 100% rename from internal/pkg/messaging/otel/tracing/consumer/consumer_tracing_options.go rename to internal/pkg/core/messaging/otel/tracing/consumer/consumer_tracing_options.go diff --git a/internal/pkg/messaging/otel/tracing/message_carrier.go b/internal/pkg/core/messaging/otel/tracing/message_carrier.go similarity index 100% rename from internal/pkg/messaging/otel/tracing/message_carrier.go rename to internal/pkg/core/messaging/otel/tracing/message_carrier.go diff --git a/internal/pkg/messaging/otel/tracing/producer/producer.go b/internal/pkg/core/messaging/otel/tracing/producer/producer.go similarity index 91% rename from internal/pkg/messaging/otel/tracing/producer/producer.go rename to internal/pkg/core/messaging/otel/tracing/producer/producer.go index 23bc6eb3..ec504151 100644 --- a/internal/pkg/messaging/otel/tracing/producer/producer.go +++ b/internal/pkg/core/messaging/otel/tracing/producer/producer.go @@ -5,10 +5,10 @@ import ( "fmt" "time" + messageHeader "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/messageheader" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/otel/tracing" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" - messageHeader "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/message_header" - messageTracing "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" @@ -37,14 +37,14 @@ func StartProducerSpan( // If there's a span context in the message, use that as the parent context. // extracts the tracing from the header and puts it into the context - carrier := messageTracing.NewMessageCarrier(meta) + carrier := tracing.NewMessageCarrier(meta) parentSpanContext := otel.GetTextMapPropagator().Extract(ctx, carrier) 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 - ctx, span := messageTracing.MessagingTracer.Start( + ctx, span := tracing.MessagingTracer.Start( parentSpanContext, fmt.Sprintf("%s %s", producerTracingOptions.Destination, "send"), opts...) @@ -67,7 +67,7 @@ func StartProducerSpan( func FinishProducerSpan(span trace.Span, err error) error { messageName := utils.GetSpanAttribute( span, - messageTracing.MessageName, + tracing.MessageName, ).Value.AsString() if err != nil { @@ -110,12 +110,12 @@ func getTraceOptions( attrs := []attribute.KeyValue{ semconv.MessageIDKey.String(message.GeMessageId()), semconv.MessagingMessageConversationID(correlationId), - attribute.Key(messageTracing.MessageType). + attribute.Key(tracing.MessageType). String(message.GetEventTypeName()), - attribute.Key(messageTracing.MessageName). + attribute.Key(tracing.MessageName). String(messageHeader.GetMessageName(*meta)), - attribute.Key(messageTracing.Payload).String(payload), - attribute.String(messageTracing.Headers, meta.ToJson()), + attribute.Key(tracing.Payload).String(payload), + attribute.String(tracing.Headers, meta.ToJson()), attribute.Key(constants.Timestamp).Int64(time.Now().UnixMilli()), semconv.MessagingDestinationName(producerTracingOptions.Destination), semconv.MessagingSystemKey.String( diff --git a/internal/pkg/messaging/otel/tracing/producer/producer_tracing_options.go b/internal/pkg/core/messaging/otel/tracing/producer/producer_tracing_options.go similarity index 100% rename from internal/pkg/messaging/otel/tracing/producer/producer_tracing_options.go rename to internal/pkg/core/messaging/otel/tracing/producer/producer_tracing_options.go diff --git a/internal/pkg/messaging/otel/tracing/trace.go b/internal/pkg/core/messaging/otel/tracing/trace.go similarity index 100% rename from internal/pkg/messaging/otel/tracing/trace.go rename to internal/pkg/core/messaging/otel/tracing/trace.go diff --git a/internal/pkg/core/messaging/persistmessage/message_persistence_repository.go b/internal/pkg/core/messaging/persistmessage/message_persistence_repository.go new file mode 100644 index 00000000..efff7d2f --- /dev/null +++ b/internal/pkg/core/messaging/persistmessage/message_persistence_repository.go @@ -0,0 +1,21 @@ +package persistmessage + +import "context" + +type MessagePersistenceRepository interface { + Add(ctx context.Context, storeMessage *StoreMessage) error + Update(ctx context.Context, storeMessage *StoreMessage) error + ChangeState( + ctx context.Context, + messageID string, + status MessageStatus, + ) error + GetAll(ctx context.Context) ([]*StoreMessage, error) + GetByFilter( + ctx context.Context, + predicate func(*StoreMessage) bool, + ) ([]*StoreMessage, error) + GetById(ctx context.Context, id string) (*StoreMessage, error) + Remove(ctx context.Context, storeMessage *StoreMessage) (bool, error) + CleanupMessages() +} diff --git a/internal/pkg/core/messaging/persistmessage/message_persistence_service.go b/internal/pkg/core/messaging/persistmessage/message_persistence_service.go new file mode 100644 index 00000000..7ae6258a --- /dev/null +++ b/internal/pkg/core/messaging/persistmessage/message_persistence_service.go @@ -0,0 +1,24 @@ +package persistmessage + +import ( + "context" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" +) + +type IMessagePersistenceService interface { + GetByFilter( + predicate func(StoreMessage) bool, + ctx context.Context, + ) ([]StoreMessage, error) + AddPublishMessage( + messageEnvelope types.MessageEnvelopeTMessage, + ctx context.Context, + ) error + AddReceivedMessage( + messageEnvelope types.MessageEnvelope, + ctx context.Context, + ) error + Process(messageID string, ctx context.Context) error + ProcessAll(ctx context.Context) error +} diff --git a/internal/pkg/core/messaging/persistmessage/store_message.go b/internal/pkg/core/messaging/persistmessage/store_message.go new file mode 100644 index 00000000..c8fd3025 --- /dev/null +++ b/internal/pkg/core/messaging/persistmessage/store_message.go @@ -0,0 +1,53 @@ +package persistmessage + +import "time" + +type MessageDeliveryType int + +const ( + Outbox MessageDeliveryType = 1 + Inbox MessageDeliveryType = 2 + Internal MessageDeliveryType = 4 +) + +type MessageStatus int + +const ( + Stored MessageStatus = 1 + Processed MessageStatus = 2 +) + +type StoreMessage struct { + ID string + DataType string + Data string + Created time.Time + RetryCount int + MessageStatus MessageStatus + DeliveryType MessageDeliveryType +} + +func NewStoreMessage( + id string, + dataType string, + data string, + deliveryType MessageDeliveryType, +) StoreMessage { + return StoreMessage{ + ID: id, + DataType: dataType, + Data: data, + Created: time.Now(), + MessageStatus: Stored, + RetryCount: 0, + DeliveryType: deliveryType, + } +} + +func (sm *StoreMessage) ChangeState(messageStatus MessageStatus) { + sm.MessageStatus = messageStatus +} + +func (sm *StoreMessage) IncreaseRetry() { + sm.RetryCount++ +} diff --git a/internal/pkg/messaging/pipeline/consumer_pipeline.go b/internal/pkg/core/messaging/pipeline/consumer_pipeline.go similarity index 95% rename from internal/pkg/messaging/pipeline/consumer_pipeline.go rename to internal/pkg/core/messaging/pipeline/consumer_pipeline.go index 4aff0d9c..ea0a6d3e 100644 --- a/internal/pkg/messaging/pipeline/consumer_pipeline.go +++ b/internal/pkg/core/messaging/pipeline/consumer_pipeline.go @@ -3,7 +3,7 @@ package pipeline import ( "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" ) // ConsumerHandlerFunc is a continuation for the next task to execute in the pipeline diff --git a/internal/pkg/messaging/pipeline/consumer_pipeline_configuration.go b/internal/pkg/core/messaging/pipeline/consumer_pipeline_configuration.go similarity index 100% rename from internal/pkg/messaging/pipeline/consumer_pipeline_configuration.go rename to internal/pkg/core/messaging/pipeline/consumer_pipeline_configuration.go diff --git a/internal/pkg/messaging/pipeline/consumer_pipeline_configuration_builder.go b/internal/pkg/core/messaging/pipeline/consumer_pipeline_configuration_builder.go similarity index 100% rename from internal/pkg/messaging/pipeline/consumer_pipeline_configuration_builder.go rename to internal/pkg/core/messaging/pipeline/consumer_pipeline_configuration_builder.go diff --git a/internal/pkg/messaging/producer/producer.go b/internal/pkg/core/messaging/producer/producer.go similarity index 95% rename from internal/pkg/messaging/producer/producer.go rename to internal/pkg/core/messaging/producer/producer.go index 5589fd13..fa55a319 100644 --- a/internal/pkg/messaging/producer/producer.go +++ b/internal/pkg/core/messaging/producer/producer.go @@ -3,8 +3,8 @@ package producer import ( "context" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" ) type Producer interface { diff --git a/internal/pkg/messaging/producer/producer_builder.go b/internal/pkg/core/messaging/producer/producer_builder.go similarity index 100% rename from internal/pkg/messaging/producer/producer_builder.go rename to internal/pkg/core/messaging/producer/producer_builder.go diff --git a/internal/pkg/messaging/types/message.go b/internal/pkg/core/messaging/types/message.go similarity index 100% rename from internal/pkg/messaging/types/message.go rename to internal/pkg/core/messaging/types/message.go diff --git a/internal/pkg/messaging/types/message_consume_context.go b/internal/pkg/core/messaging/types/message_consume_context.go similarity index 100% rename from internal/pkg/messaging/types/message_consume_context.go rename to internal/pkg/core/messaging/types/message_consume_context.go diff --git a/internal/pkg/core/messaging/types/message_envelope.go b/internal/pkg/core/messaging/types/message_envelope.go new file mode 100644 index 00000000..26a8091f --- /dev/null +++ b/internal/pkg/core/messaging/types/message_envelope.go @@ -0,0 +1,37 @@ +package types + +type MessageEnvelope struct { + Message interface{} + Headers map[string]interface{} +} + +func NewMessageEnvelope( + message interface{}, + headers map[string]interface{}, +) *MessageEnvelope { + if headers == nil { + headers = make(map[string]interface{}) + } + + return &MessageEnvelope{ + Message: message, + Headers: headers, + } +} + +type MessageEnvelopeTMessage struct { + *MessageEnvelope + MessageTMessage interface{} +} + +func NewMessageEnvelopeTMessage( + messageTMessage interface{}, + headers map[string]interface{}, +) *MessageEnvelopeTMessage { + messageEnvelope := NewMessageEnvelope(messageTMessage, headers) + + return &MessageEnvelopeTMessage{ + MessageEnvelope: messageEnvelope, + MessageTMessage: messageTMessage, + } +} diff --git a/internal/pkg/messaging/types/mock_IMessage_test.go b/internal/pkg/core/messaging/types/mock_IMessage_test.go similarity index 100% rename from internal/pkg/messaging/types/mock_IMessage_test.go rename to internal/pkg/core/messaging/types/mock_IMessage_test.go diff --git a/internal/pkg/messaging/utils/utils.go b/internal/pkg/core/messaging/utils/utils.go similarity index 97% rename from internal/pkg/messaging/utils/utils.go rename to internal/pkg/core/messaging/utils/utils.go index 534a973b..10a21e27 100644 --- a/internal/pkg/messaging/utils/utils.go +++ b/internal/pkg/core/messaging/utils/utils.go @@ -3,8 +3,8 @@ package utils import ( "reflect" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/ahmetb/go-linq/v3" "github.com/iancoleman/strcase" diff --git a/internal/pkg/core/serializer/event_serializer.go b/internal/pkg/core/serializer/event_serializer.go index 3a4995c0..c7338d96 100644 --- a/internal/pkg/core/serializer/event_serializer.go +++ b/internal/pkg/core/serializer/event_serializer.go @@ -4,8 +4,8 @@ import ( "reflect" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/events" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "emperror.dev/errors" ) diff --git a/internal/pkg/core/utils/utils.go b/internal/pkg/core/utils/utils.go index f57bde76..fe90fc73 100644 --- a/internal/pkg/core/utils/utils.go +++ b/internal/pkg/core/utils/utils.go @@ -5,7 +5,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/domain" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/events" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/ahmetb/go-linq/v3" ) diff --git a/internal/pkg/elasticsearch/elastic_options.go b/internal/pkg/elasticsearch/elastic_options.go index 67e5f466..56a89c3e 100644 --- a/internal/pkg/elasticsearch/elastic_options.go +++ b/internal/pkg/elasticsearch/elastic_options.go @@ -3,7 +3,7 @@ package elasticsearch import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/iancoleman/strcase" ) diff --git a/internal/pkg/eventstroredb/aggregate_store.go b/internal/pkg/eventstroredb/aggregate_store.go index 5b58d2a8..ccedc555 100644 --- a/internal/pkg/eventstroredb/aggregate_store.go +++ b/internal/pkg/eventstroredb/aggregate_store.go @@ -17,7 +17,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "emperror.dev/errors" "github.com/EventStore/EventStore-Client-Go/esdb" diff --git a/internal/pkg/eventstroredb/config/eventstoredb_options.go b/internal/pkg/eventstroredb/config/eventstoredb_options.go index 5046bbeb..7f1d4bc7 100644 --- a/internal/pkg/eventstroredb/config/eventstoredb_options.go +++ b/internal/pkg/eventstroredb/config/eventstoredb_options.go @@ -5,7 +5,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/iancoleman/strcase" ) diff --git a/internal/pkg/eventstroredb/esdb_serilizer.go b/internal/pkg/eventstroredb/esdb_serilizer.go index 6e955dc0..2de85f15 100644 --- a/internal/pkg/eventstroredb/esdb_serilizer.go +++ b/internal/pkg/eventstroredb/esdb_serilizer.go @@ -13,7 +13,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/models/stream_position/truncatePosition" expectedStreamVersion "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/models/stream_version" esErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/eventstroredb/errors" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "emperror.dev/errors" "github.com/EventStore/EventStore-Client-Go/esdb" diff --git a/internal/pkg/eventstroredb/esdb_subscription_check_point_repository.go b/internal/pkg/eventstroredb/esdb_subscription_check_point_repository.go index 5293ebc8..739b5321 100644 --- a/internal/pkg/eventstroredb/esdb_subscription_check_point_repository.go +++ b/internal/pkg/eventstroredb/esdb_subscription_check_point_repository.go @@ -9,7 +9,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/events" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "emperror.dev/errors" "github.com/EventStore/EventStore-Client-Go/esdb" diff --git a/internal/pkg/eventstroredb/subscription_all_worker.go b/internal/pkg/eventstroredb/subscription_all_worker.go index c5382a44..32638336 100644 --- a/internal/pkg/eventstroredb/subscription_all_worker.go +++ b/internal/pkg/eventstroredb/subscription_all_worker.go @@ -10,7 +10,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/contracts/projection" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/eventstroredb/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "emperror.dev/errors" "github.com/EventStore/EventStore-Client-Go/esdb" diff --git a/internal/pkg/fxapp/test/test_application.go b/internal/pkg/fxapp/test/test_application.go index b750b871..b76a4060 100644 --- a/internal/pkg/fxapp/test/test_application.go +++ b/internal/pkg/fxapp/test/test_application.go @@ -2,14 +2,11 @@ package test import ( "context" - "os" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/constants" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/spf13/viper" "go.uber.org/fx" "go.uber.org/fx/fxtest" ) @@ -94,7 +91,7 @@ func (a *testApplication) Wait() <-chan fx.ShutdownSignal { } func (a *testApplication) createFxTest() *fxtest.App { - a.fixTestEnvironmentWorkingDirectory() + // a.fixTestEnvironmentWorkingDirectory() // build phase of container will do in this stage, containing provides and invokes but app not started yet and will be started in the future with `fxApp.Register` fxTestApp := CreateFxTestApp( @@ -111,15 +108,15 @@ func (a *testApplication) createFxTest() *fxtest.App { return fxTestApp } -func (a *testApplication) fixTestEnvironmentWorkingDirectory() { - currentWD, _ := os.Getwd() - a.logger.Infof("Current test working directory is: %s", currentWD) - - rootDir := viper.GetString(constants.AppRootPath) - if rootDir != "" { - _ = os.Chdir(rootDir) - - newWD, _ := os.Getwd() - a.logger.Infof("New test working directory is: %s", newWD) - } -} +//func (a *testApplication) fixTestEnvironmentWorkingDirectory() { +// currentWD, _ := os.Getwd() +// a.logger.Infof("Current test working directory is: %s", currentWD) +// +// rootDir := viper.GetString(constants.AppRootPath) +// if rootDir != "" { +// _ = os.Chdir(rootDir) +// +// newWD, _ := os.Getwd() +// a.logger.Infof("New test working directory is: %s", newWD) +// } +//} diff --git a/internal/pkg/go.mod b/internal/pkg/go.mod index 88d4b62d..c664b8e9 100644 --- a/internal/pkg/go.mod +++ b/internal/pkg/go.mod @@ -10,11 +10,13 @@ require ( github.com/ahmetb/go-linq/v3 v3.2.0 github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de github.com/avast/retry-go v3.0.0+incompatible + github.com/brianvoe/gofakeit/v6 v6.25.0 github.com/caarlos0/env/v8 v8.0.0 github.com/docker/docker v24.0.6+incompatible github.com/docker/go-connections v0.4.0 github.com/doug-martin/goqu/v9 v9.18.0 github.com/elastic/go-elasticsearch/v8 v8.10.0 + github.com/glebarez/sqlite v1.10.0 github.com/go-playground/validator v9.31.0+incompatible github.com/go-resty/resty/v2 v2.9.1 github.com/go-testfixtures/testfixtures/v3 v3.9.0 @@ -80,7 +82,7 @@ require ( go.uber.org/zap v1.26.0 google.golang.org/grpc v1.58.2 gorm.io/driver/postgres v1.5.2 - gorm.io/gorm v1.25.4 + gorm.io/gorm v1.25.5 gorm.io/plugin/opentelemetry v0.1.4 ) @@ -104,9 +106,11 @@ require ( github.com/docker/cli v24.0.6+incompatible // indirect github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/elastic/elastic-transport-go/v8 v8.3.0 // indirect github.com/fatih/color v1.15.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/glebarez/go-sqlite v1.21.2 // indirect github.com/go-faster/city v1.0.1 // indirect github.com/go-faster/errors v0.6.1 // indirect github.com/go-logr/logr v1.2.4 // indirect @@ -170,6 +174,7 @@ require ( github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/shirou/gopsutil/v3 v3.23.9 // indirect @@ -216,8 +221,13 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect mellium.im/sasl v0.3.1 // indirect + modernc.org/libc v1.24.1 // indirect + modernc.org/mathutil v1.6.0 // indirect + modernc.org/memory v1.6.0 // indirect + modernc.org/sqlite v1.25.0 // indirect ) diff --git a/internal/pkg/go.sum b/internal/pkg/go.sum index cc48b9f9..d740df7a 100644 --- a/internal/pkg/go.sum +++ b/internal/pkg/go.sum @@ -87,6 +87,8 @@ github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/brianvoe/gofakeit/v6 v6.25.0 h1:ZpFjktOpLZUeF8q223o0rUuXtA+m5qW5srjvVi+JkXk= +github.com/brianvoe/gofakeit/v6 v6.25.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= @@ -180,6 +182,10 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= +github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= +github.com/glebarez/sqlite v1.10.0 h1:u4gt8y7OND/cCei/NMHmfbLxF6xP2wgKcT/BJf2pYkc= +github.com/glebarez/sqlite v1.10.0/go.mod h1:IJ+lfSOmiekhQsFTJRx/lHtGYmCdtAiTaf5wI9u5uHA= github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw= github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw= github.com/go-faster/errors v0.6.1 h1:nNIPOBkprlKzkThvS/0YaX8Zs9KewLCOSFQS5BU06FI= @@ -464,8 +470,6 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mcuadros/go-defaults v1.2.0 h1:FODb8WSf0uGaY8elWJAkoLL0Ri6AlZ1bFlenk56oZtc= github.com/mcuadros/go-defaults v1.2.0/go.mod h1:WEZtHEVIGYVDqkKSWBdWKUVdRyKlMfulPaGDWIVeCWY= -github.com/mehdihadeli/go-mediatr v1.2.0 h1:XkzYF/uGfW4pwPWYAxKyY+mO6l989PbmCQWSYHuCZtU= -github.com/mehdihadeli/go-mediatr v1.2.0/go.mod h1:I9LuExxAKz6cTDJyP/SSDSmkHaPHK1/usnvEXjUY47k= github.com/mehdihadeli/go-mediatr v1.3.0 h1:hrb5Scp/nsiR3Y62mjZ0Tc5UX/dRJl4nDFkINBEIESA= github.com/mehdihadeli/go-mediatr v1.3.0/go.mod h1:lsG+hyH+pEOhmZiZl0KPO72BcZiEReF03CBk4GVJB0k= github.com/michaelklishin/rabbit-hole v1.5.0 h1:Bex27BiFDsijCM9D0ezSHqyy0kehpYHuNKaPqq/a4RM= @@ -1207,8 +1211,8 @@ gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0= gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8= gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c= gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I= -gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= -gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= +gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/plugin/opentelemetry v0.1.4 h1:7p0ocWELjSSRI7NCKPW2mVe6h43YPini99sNJcbsTuc= gorm.io/plugin/opentelemetry v0.1.4/go.mod h1:tndJHOdvPT0pyGhOb8E2209eXJCUxhC5UpKw7bGVWeI= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= diff --git a/internal/pkg/gorm_postgres/repository/gorm_generic_repository_test.go b/internal/pkg/gorm_postgres/repository/gorm_generic_repository_test.go deleted file mode 100644 index 7b4ec5b2..00000000 --- a/internal/pkg/gorm_postgres/repository/gorm_generic_repository_test.go +++ /dev/null @@ -1,510 +0,0 @@ -package repository - -import ( - "context" - "log" - "testing" - - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/data" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/data/specification" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - gorm2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/testcontainer/gorm" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - - uuid "github.com/satori/go.uuid" - "github.com/stretchr/testify/assert" - "gorm.io/gorm" - - _ "github.com/lib/pq" // postgres driver -) - -// Product is a domain_events entity -type Product struct { - ID uuid.UUID - Name string - Weight int - IsAvailable bool -} - -// ProductGorm is DTO used to map Product entity to database -type ProductGorm struct { - ID uuid.UUID `gorm:"primaryKey;column:id"` - Name string `gorm:"column:name"` - Weight int `gorm:"column:weight"` - IsAvailable bool `gorm:"column:is_available"` -} - -func init() { - err := mapper.CreateMap[*ProductGorm, *Product]() - if err != nil { - log.Fatal(err) - } - - err = mapper.CreateMap[*Product, *ProductGorm]() - if err != nil { - log.Fatal(err) - } -} - -func Test_Add(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepository(ctx, t) - - product := &ProductGorm{ - ID: uuid.NewV4(), - Name: "added_product", - Weight: 100, - IsAvailable: true, - } - - err = repository.Add(ctx, product) - if err != nil { - t.Fatal(err) - } - - p, err := repository.GetById(ctx, product.ID) - if err != nil { - return - } - - assert.NotNil(t, p) - assert.Equal(t, product.ID, p.ID) -} - -func Test_Add_With_Data_Model(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepositoryWithDataModel(ctx, t) - if err != nil { - t.Fatal(err) - } - - product := &Product{ - ID: uuid.NewV4(), - Name: "added_product", - Weight: 100, - IsAvailable: true, - } - - err = repository.Add(ctx, product) - if err != nil { - t.Fatal(err) - } - - p, err := repository.GetById(ctx, product.ID) - if err != nil { - return - } - - assert.NotNil(t, p) - assert.Equal(t, product.ID, p.ID) -} - -func Test_Get_By_Id(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepository(ctx, t) - if err != nil { - t.Fatal(err) - } - - all, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - return - } - p := all.Items[0] - - testCases := []struct { - Name string - ProductId uuid.UUID - ExpectResult *ProductGorm - }{ - { - Name: "ExistingProduct", - ProductId: p.ID, - ExpectResult: p, - }, - { - Name: "NonExistingProduct", - ProductId: uuid.NewV4(), - ExpectResult: nil, - }, - } - - for _, c := range testCases { - c := c - t.Run(c.Name, func(t *testing.T) { - t.Parallel() - res, err := repository.GetById(ctx, c.ProductId) - if c.ExpectResult == nil { - assert.Error(t, err) - assert.True(t, customErrors.IsNotFoundError(err)) - assert.Nil(t, res) - } else { - assert.NoError(t, err) - assert.NotNil(t, res) - assert.Equal(t, p.ID, res.ID) - } - }) - } -} - -func Test_Get_By_Id_With_Data_Model(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepositoryWithDataModel(ctx, t) - if err != nil { - t.Fatal(err) - } - - all, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - return - } - p := all.Items[0] - - testCases := []struct { - Name string - ProductId uuid.UUID - ExpectResult *Product - }{ - { - Name: "ExistingProduct", - ProductId: p.ID, - ExpectResult: p, - }, - { - Name: "NonExistingProduct", - ProductId: uuid.NewV4(), - ExpectResult: nil, - }, - } - - for _, c := range testCases { - c := c - t.Run(c.Name, func(t *testing.T) { - t.Parallel() - res, err := repository.GetById(ctx, c.ProductId) - if c.ExpectResult == nil { - assert.Error(t, err) - assert.True(t, customErrors.IsNotFoundError(err)) - assert.Nil(t, res) - } else { - assert.NoError(t, err) - assert.NotNil(t, res) - assert.Equal(t, p.ID, res.ID) - } - }) - } -} - -func Test_Get_All(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepository(ctx, t) - if err != nil { - t.Fatal(err) - } - - models, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - t.Fatal(err) - } - - assert.NotEmpty(t, models.Items) -} - -func Test_Get_All_With_Data_Model(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepositoryWithDataModel(ctx, t) - if err != nil { - t.Fatal(err) - } - - models, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - t.Fatal(err) - } - - assert.NotEmpty(t, models.Items) -} - -func Test_Search(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepository(ctx, t) - if err != nil { - t.Fatal(err) - } - - models, err := repository.Search( - ctx, - "seed_product1", - utils.NewListQuery(10, 1), - ) - if err != nil { - t.Fatal(err) - } - - assert.NotEmpty(t, models.Items) - assert.Equal(t, len(models.Items), 1) -} - -func Test_Search_With_Data_Model(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepositoryWithDataModel(ctx, t) - - models, err := repository.Search( - ctx, - "seed_product1", - utils.NewListQuery(10, 1), - ) - if err != nil { - t.Fatal(err) - } - - assert.NotEmpty(t, models.Items) - assert.Equal(t, len(models.Items), 1) -} - -func Test_Where(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepository(ctx, t) - - models, err := repository.GetByFilter( - ctx, - map[string]interface{}{"name": "seed_product1"}, - ) - if err != nil { - t.Fatal(err) - } - - assert.NotEmpty(t, models) - assert.Equal(t, len(models), 1) -} - -func Test_Where_With_Data_Model(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepositoryWithDataModel(ctx, t) - - models, err := repository.GetByFilter( - ctx, - map[string]interface{}{"name": "seed_product1"}, - ) - if err != nil { - t.Fatal(err) - } - - assert.NotEmpty(t, models) - assert.Equal(t, len(models), 1) -} - -func Test_Update(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepository(ctx, t) - - products, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - t.Fatal(err) - } - product := products.Items[0] - - product.Name = "product2_updated" - err = repository.Update(ctx, product) - if err != nil { - t.Fatal(err) - } - - single, err := repository.GetById(ctx, product.ID) - if err != nil { - t.Fatal(err) - } - assert.NotNil(t, single) - assert.Equal(t, "product2_updated", single.Name) -} - -func Test_Update_With_Data_Model(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepositoryWithDataModel(ctx, t) - - products, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - t.Fatal(err) - } - product := products.Items[0] - - product.Name = "product2_updated" - err = repository.Update(ctx, product) - if err != nil { - t.Fatal(err) - } - - single, err := repository.GetById(ctx, product.ID) - if err != nil { - t.Fatal(err) - } - assert.NotNil(t, single) - assert.Equal(t, "product2_updated", single.Name) -} - -func Test_Delete(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepository(ctx, t) - - products, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - t.Fatal(err) - } - product := products.Items[0] - - err = repository.Delete(ctx, product.ID) - if err != nil { - return - } - - single, err := repository.GetById(ctx, product.ID) - assert.Nil(t, single) -} - -func Test_Delete_With_Data_Model(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepositoryWithDataModel(ctx, t) - - products, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - t.Fatal(err) - } - product := products.Items[0] - - err = repository.Delete(ctx, product.ID) - if err != nil { - return - } - - single, err := repository.GetById(ctx, product.ID) - assert.Nil(t, single) -} - -func Test_Count(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepository(ctx, t) - if err != nil { - t.Fatal(err) - } - - count := repository.Count(ctx) - - assert.Equal(t, count, int64(2)) -} - -func Test_Count_With_Data_Model(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepositoryWithDataModel(ctx, t) - if err != nil { - t.Fatal(err) - } - - count := repository.Count(ctx) - - assert.Equal(t, count, int64(2)) -} - -func Test_Find(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepository(ctx, t) - if err != nil { - t.Fatal(err) - } - - entities, err := repository.Find( - ctx, - specification.And( - specification.Equal("is_available", true), - specification.Equal("name", "seed_product1"), - ), - ) - if err != nil { - return - } - assert.Equal(t, len(entities), 1) -} - -func Test_Find_With_Data_Model(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericGormRepositoryWithDataModel(ctx, t) - if err != nil { - t.Fatal(err) - } - - entities, err := repository.Find( - ctx, - specification.And( - specification.Equal("is_available", true), - specification.Equal("name", "seed_product1"), - ), - ) - if err != nil { - return - } - assert.Equal(t, len(entities), 1) -} - -func setupGenericGormRepositoryWithDataModel( - ctx context.Context, - t *testing.T, -) (data.GenericRepositoryWithDataModel[*ProductGorm, *Product], error) { - db, err := gorm2.NewGormTestContainers(defaultLogger.GetLogger()). - Start(ctx, t) - if err != nil { - return nil, err - } - - err = seedAndMigration(ctx, db) - if err != nil { - return nil, err - } - - return NewGenericGormRepositoryWithDataModel[*ProductGorm, *Product]( - db, - ), nil -} - -func setupGenericGormRepository( - ctx context.Context, - t *testing.T, -) (data.GenericRepository[*ProductGorm], error) { - db, err := gorm2.NewGormTestContainers(defaultLogger.GetLogger()). - Start(ctx, t) - - err = seedAndMigration(ctx, db) - if err != nil { - return nil, err - } - - return NewGenericGormRepository[*ProductGorm](db), nil -} - -func seedAndMigration(ctx context.Context, db *gorm.DB) error { - err := db.AutoMigrate(ProductGorm{}) - if err != nil { - return err - } - - seedProducts := []*ProductGorm{ - { - ID: uuid.NewV4(), - Name: "seed_product1", - Weight: 100, - IsAvailable: true, - }, - { - ID: uuid.NewV4(), - Name: "seed_product2", - Weight: 100, - IsAvailable: true, - }, - } - - err = db.WithContext(ctx).Create(seedProducts).Error - if err != nil { - return err - } - return nil -} diff --git a/internal/pkg/grpc/config/grpc_options.go b/internal/pkg/grpc/config/grpc_options.go index 773b32c7..0181e499 100644 --- a/internal/pkg/grpc/config/grpc_options.go +++ b/internal/pkg/grpc/config/grpc_options.go @@ -3,7 +3,7 @@ package config import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/iancoleman/strcase" ) diff --git a/internal/pkg/grpc/grpcErrors/grpc_errors.go b/internal/pkg/grpc/grpcErrors/grpc_errors.go index 13424bc7..2d4f41aa 100644 --- a/internal/pkg/grpc/grpcErrors/grpc_errors.go +++ b/internal/pkg/grpc/grpcErrors/grpc_errors.go @@ -5,7 +5,7 @@ import ( "fmt" "time" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" diff --git a/internal/pkg/http/custom_echo/config/echo_http_options.go b/internal/pkg/http/custom_echo/config/echo_http_options.go index 290de0ea..c0c724b7 100644 --- a/internal/pkg/http/custom_echo/config/echo_http_options.go +++ b/internal/pkg/http/custom_echo/config/echo_http_options.go @@ -6,7 +6,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/iancoleman/strcase" ) diff --git a/internal/pkg/http/http_errors/problemDetails/problem_detail_parser.go b/internal/pkg/http/http_errors/problemDetails/problem_detail_parser.go index bc5deaf0..1f6ce148 100644 --- a/internal/pkg/http/http_errors/problemDetails/problem_detail_parser.go +++ b/internal/pkg/http/http_errors/problemDetails/problem_detail_parser.go @@ -8,7 +8,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/constants" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" "emperror.dev/errors" diff --git a/internal/pkg/http/http_errors/problemDetails/problem_details.go b/internal/pkg/http/http_errors/problemDetails/problem_details.go index aa85b40c..b67c499d 100644 --- a/internal/pkg/http/http_errors/problemDetails/problem_details.go +++ b/internal/pkg/http/http_errors/problemDetails/problem_details.go @@ -8,8 +8,8 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/contracts" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "emperror.dev/errors" ) diff --git a/internal/pkg/logger/config/log_options.go b/internal/pkg/logger/config/log_options.go index a297d1e1..69ab106a 100644 --- a/internal/pkg/logger/config/log_options.go +++ b/internal/pkg/logger/config/log_options.go @@ -4,7 +4,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/models" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/iancoleman/strcase" ) diff --git a/internal/pkg/logger/default_logger/default_logger.go b/internal/pkg/logger/defaultlogger/default_logger.go similarity index 100% rename from internal/pkg/logger/default_logger/default_logger.go rename to internal/pkg/logger/defaultlogger/default_logger.go diff --git a/internal/pkg/logger/pipelines/logging_pipeline.go b/internal/pkg/logger/pipelines/logging_pipeline.go index ca8889b7..069bf62f 100644 --- a/internal/pkg/logger/pipelines/logging_pipeline.go +++ b/internal/pkg/logger/pipelines/logging_pipeline.go @@ -1,4 +1,4 @@ -package pipelines +package loggingpipelines import ( "context" @@ -6,7 +6,7 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/mehdihadeli/go-mediatr" ) @@ -15,7 +15,7 @@ type requestLoggerPipeline struct { logger logger.Logger } -func NewLoggingPipeline(l logger.Logger) mediatr.PipelineBehavior { +func NewMediatorLoggingPipeline(l logger.Logger) mediatr.PipelineBehavior { return &requestLoggerPipeline{logger: l} } diff --git a/internal/pkg/mapper/mapper.go b/internal/pkg/mapper/mapper.go index 4adb891e..2d1826ed 100644 --- a/internal/pkg/mapper/mapper.go +++ b/internal/pkg/mapper/mapper.go @@ -7,8 +7,8 @@ import ( "fmt" "reflect" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" - reflectionHelper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/reflection_helper" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" + reflectionHelper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/reflectionhelper" "emperror.dev/errors" "github.com/ahmetb/go-linq/v3" diff --git a/internal/pkg/messaging/bus/bus.go b/internal/pkg/messaging/bus/bus.go deleted file mode 100644 index 9719400f..00000000 --- a/internal/pkg/messaging/bus/bus.go +++ /dev/null @@ -1,12 +0,0 @@ -package bus - -import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" -) - -type Bus interface { - producer.Producer - consumer.BusControl - consumer.ConsumerConnector -} diff --git a/internal/pkg/migration/goose/postgres.go b/internal/pkg/migration/goose/postgres.go index 91e3d0c3..11298cc1 100644 --- a/internal/pkg/migration/goose/postgres.go +++ b/internal/pkg/migration/goose/postgres.go @@ -43,21 +43,34 @@ func (m *goosePostgresMigrator) Down(_ context.Context, version uint) error { return err } -func (m *goosePostgresMigrator) executeCommand(command migration.CommandType, version uint) error { +func (m *goosePostgresMigrator) executeCommand( + command migration.CommandType, + version uint, +) error { switch command { case migration.Up: if version == 0 { - // In test environment, ewe need a fix for applying application working directory correctly. we will apply this in our environment setup process in `config/environment` file + // In test environment, we need a fix for applying application working directory correctly. we will apply this in our environment setup process in `config/environment` file return goose.Run("up", m.db, m.config.MigrationsDir) } - return goose.Run("up-to VERSION ", m.db, m.config.MigrationsDir, strconv.FormatUint(uint64(version), 10)) + return goose.Run( + "up-to VERSION ", + m.db, + m.config.MigrationsDir, + strconv.FormatUint(uint64(version), 10), + ) case migration.Down: if version == 0 { return goose.Run("down", m.db, m.config.MigrationsDir) } - return goose.Run("down-to VERSION ", m.db, m.config.MigrationsDir, strconv.FormatUint(uint64(version), 10)) + return goose.Run( + "down-to VERSION ", + m.db, + m.config.MigrationsDir, + strconv.FormatUint(uint64(version), 10), + ) default: return errors.New("invalid migration direction") } diff --git a/internal/pkg/migration/migration_options.go b/internal/pkg/migration/migration_options.go index 15d65ccb..9e442539 100644 --- a/internal/pkg/migration/migration_options.go +++ b/internal/pkg/migration/migration_options.go @@ -3,7 +3,7 @@ package migration import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/iancoleman/strcase" ) diff --git a/internal/pkg/mongodb/helpers.go b/internal/pkg/mongodb/helpers.go index 3f10068f..6f180059 100644 --- a/internal/pkg/mongodb/helpers.go +++ b/internal/pkg/mongodb/helpers.go @@ -31,28 +31,31 @@ func Paginate[T any]( limit := int64(listQuery.GetLimit()) skip := int64(listQuery.GetOffset()) - cursor, err := collection.Find(ctx, filter, &options.FindOptions{ - Limit: &limit, - Skip: &skip, - }) + cursor, err := collection.Find( + ctx, + filter, + &options.FindOptions{ + Limit: &limit, + Skip: &skip, + }) if err != nil { - return nil, errors.WrapIf(err, "Find") + return nil, err } - defer cursor.Close(ctx) // nolint: errcheck - products := make([]T, 0, listQuery.GetSize()) + defer cursor.Close(ctx) - for cursor.Next(ctx) { - var prod T - if err := cursor.Decode(&prod); err != nil { - return nil, errors.WrapIf(err, "Find") - } - products = append(products, prod) - } + var items []T - if err := cursor.Err(); err != nil { - return nil, errors.WrapIf(err, "cursor.Err") + // https://www.mongodb.com/docs/drivers/go/current/fundamentals/crud/read-operations/cursor/#retrieve-all-documents + err = cursor.All(ctx, &items) + if err != nil { + return nil, err } - return utils.NewListResult[T](products, listQuery.GetSize(), listQuery.GetPage(), count), nil + return utils.NewListResult[T]( + items, + listQuery.GetSize(), + listQuery.GetPage(), + count, + ), nil } diff --git a/internal/pkg/mongodb/mongo_options.go b/internal/pkg/mongodb/mongo_options.go index 4ff3a0f8..e75e3d62 100644 --- a/internal/pkg/mongodb/mongo_options.go +++ b/internal/pkg/mongodb/mongo_options.go @@ -3,7 +3,7 @@ package mongodb import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/iancoleman/strcase" ) diff --git a/internal/pkg/mongodb/repository/mongo_generic_repository.go b/internal/pkg/mongodb/repository/mongo_generic_repository.go index 32b74215..2142dc4d 100644 --- a/internal/pkg/mongodb/repository/mongo_generic_repository.go +++ b/internal/pkg/mongodb/repository/mongo_generic_repository.go @@ -9,8 +9,8 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" - reflectionHelper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/reflection_helper" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + reflectionHelper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/reflectionhelper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "emperror.dev/errors" @@ -61,7 +61,10 @@ func NewGenericMongoRepository[TEntity interface{}]( } } -func (m *mongoGenericRepository[TDataModel, TEntity]) Add(ctx context.Context, entity TEntity) error { +func (m *mongoGenericRepository[TDataModel, TEntity]) Add( + ctx context.Context, + entity TEntity, +) error { dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() modelType := typeMapper.GetTypeFromGeneric[TEntity]() @@ -91,7 +94,10 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) Add(ctx context.Context, e return nil } -func (m *mongoGenericRepository[TDataModel, TEntity]) AddAll(ctx context.Context, entities []TEntity) error { +func (m *mongoGenericRepository[TDataModel, TEntity]) AddAll( + ctx context.Context, + entities []TEntity, +) error { for _, entity := range entities { err := m.Add(ctx, entity) if err != nil { @@ -102,7 +108,10 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) AddAll(ctx context.Context return nil } -func (m *mongoGenericRepository[TDataModel, TEntity]) GetById(ctx context.Context, id uuid.UUID) (TEntity, error) { +func (m *mongoGenericRepository[TDataModel, TEntity]) GetById( + ctx context.Context, + id uuid.UUID, +) (TEntity, error) { dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() modelType := typeMapper.GetTypeFromGeneric[TEntity]() collection := m.db.Database(m.databaseName).Collection(m.collectionName) @@ -118,12 +127,18 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) GetById(ctx context.Contex if err == mongo.ErrNoDocuments { return *new(TEntity), customErrors.NewNotFoundErrorWrap( err, - fmt.Sprintf("can't find the entity with id %s into the database.", id.String()), + fmt.Sprintf( + "can't find the entity with id %s into the database.", + id.String(), + ), ) } return *new(TEntity), errors.WrapIf( err, - fmt.Sprintf("can't find the entity with id %s into the database.", id.String()), + fmt.Sprintf( + "can't find the entity with id %s into the database.", + id.String(), + ), ) } return model, nil @@ -153,7 +168,12 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) GetAll( collection := m.db.Database(m.databaseName).Collection(m.collectionName) if modelType == dataModelType { - result, err := mongodb.Paginate[TEntity](ctx, listQuery, collection, nil) + result, err := mongodb.Paginate[TEntity]( + ctx, + listQuery, + collection, + nil, + ) if err != nil { return nil, err } @@ -181,19 +201,31 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) Search( collection := m.db.Database(m.databaseName).Collection(m.collectionName) if modelType == dataModelType { - fields := reflectionHelper.GetAllFields(typeMapper.GetTypeFromGeneric[TEntity]()) + fields := reflectionHelper.GetAllFields( + typeMapper.GetTypeFromGeneric[TEntity](), + ) var a bson.A for _, field := range fields { if field.Type.Kind() != reflect.String { continue } name := strcase.ToLowerCamel(field.Name) - a = append(a, bson.D{{Key: name, Value: primitive.Regex{Pattern: searchTerm, Options: "gi"}}}) + a = append( + a, + bson.D{ + {Key: name, Value: primitive.Regex{Pattern: searchTerm}}, + }, + ) } filter := bson.D{ {Key: "$or", Value: a}, } - result, err := mongodb.Paginate[TEntity](ctx, listQuery, collection, filter) + result, err := mongodb.Paginate[TEntity]( + ctx, + listQuery, + collection, + filter, + ) if err != nil { return nil, err } @@ -206,7 +238,7 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) Search( continue } name := strcase.ToLowerCamel(field.Name) - a = append(a, bson.D{{Key: name, Value: primitive.Regex{Pattern: searchTerm, Options: "gi"}}}) + a = append(a, bson.D{{Key: name, Value: primitive.Regex{Pattern: searchTerm}}}) } filter := bson.D{ {Key: "$or", Value: a}, @@ -315,7 +347,10 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) FirstOrDefault( } } -func (m *mongoGenericRepository[TDataModel, TEntity]) Update(ctx context.Context, entity TEntity) error { +func (m *mongoGenericRepository[TDataModel, TEntity]) Update( + ctx context.Context, + entity TEntity, +) error { dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() modelType := typeMapper.GetTypeFromGeneric[TEntity]() collection := m.db.Database(m.databaseName).Collection(m.collectionName) @@ -367,7 +402,10 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) Update(ctx context.Context return nil } -func (m *mongoGenericRepository[TDataModel, TEntity]) UpdateAll(ctx context.Context, entities []TEntity) error { +func (m *mongoGenericRepository[TDataModel, TEntity]) UpdateAll( + ctx context.Context, + entities []TEntity, +) error { for _, e := range entities { err := m.Update(ctx, e) if err != nil { @@ -378,7 +416,10 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) UpdateAll(ctx context.Cont return nil } -func (m *mongoGenericRepository[TDataModel, TEntity]) Delete(ctx context.Context, id uuid.UUID) error { +func (m *mongoGenericRepository[TDataModel, TEntity]) Delete( + ctx context.Context, + id uuid.UUID, +) error { collection := m.db.Database(m.databaseName).Collection(m.collectionName) if err := collection.FindOneAndDelete(ctx, bson.M{"_id": id.String()}).Err(); err != nil { @@ -436,7 +477,9 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) SkipTake( } } -func (m *mongoGenericRepository[TDataModel, TEntity]) Count(ctx context.Context) int64 { +func (m *mongoGenericRepository[TDataModel, TEntity]) Count( + ctx context.Context, +) int64 { collection := m.db.Database(m.databaseName).Collection(m.collectionName) count, err := collection.CountDocuments(ctx, bson.M{}) if err != nil { diff --git a/internal/pkg/mongodb/repository/mongo_generic_repository_test.go b/internal/pkg/mongodb/repository/mongo_generic_repository_test.go index d36a8cd0..1ded1163 100644 --- a/internal/pkg/mongodb/repository/mongo_generic_repository_test.go +++ b/internal/pkg/mongodb/repository/mongo_generic_repository_test.go @@ -2,28 +2,24 @@ package repository import ( "context" - "log" "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/data" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/data/specification" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - mongo2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/testcontainer/mongo" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" + mongocontainer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/testcontainer/mongo" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" + "github.com/brianvoe/gofakeit/v6" uuid "github.com/satori/go.uuid" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) -const ( - DatabaseName = "catalogs_write" - CollectionName = "products" -) - // Product is a domain_events entity type Product struct { ID string @@ -39,98 +35,121 @@ type ProductMongo struct { IsAvailable bool `json:"isAvailable" bson:"isAvailable"` } -func init() { - err := mapper.CreateMap[*ProductMongo, *Product]() - if err != nil { - log.Fatal(err) - } +type mongoGenericRepositoryTest struct { + suite.Suite + databaseName string + collectionName string + mongoClient *mongo.Client + productRepository data.GenericRepository[*ProductMongo] + productRepositoryWithDataModel data.GenericRepositoryWithDataModel[*ProductMongo, *Product] + products []*ProductMongo +} + +func TestMongoGenericRepository(t *testing.T) { + suite.Run( + t, + &mongoGenericRepositoryTest{ + databaseName: "catalogs_write", + collectionName: "products", + }, + ) +} + +func (c *mongoGenericRepositoryTest) SetupSuite() { + opts, err := mongocontainer.NewMongoTestContainers(defaultLogger.GetLogger()). + PopulateContainerOptions(context.Background(), c.T()) + c.Require().NoError(err) + + mongoClient, err := mongodb.NewMongoDB(opts) + c.Require().NoError(err) + c.mongoClient = mongoClient + + c.productRepository = NewGenericMongoRepository[*ProductMongo]( + mongoClient, + c.databaseName, + c.collectionName, + ) + c.productRepositoryWithDataModel = NewGenericMongoRepositoryWithDataModel[*ProductMongo, *Product]( + mongoClient, + c.databaseName, + c.collectionName, + ) + + err = mapper.CreateMap[*ProductMongo, *Product]() + c.Require().NoError(err) err = mapper.CreateMap[*Product, *ProductMongo]() - if err != nil { - log.Fatal(err) - } + c.Require().NoError(err) +} + +func (c *mongoGenericRepositoryTest) SetupTest() { + p, err := c.seedData(context.Background()) + c.Require().NoError(err) + c.products = p } -func Test_Add(t *testing.T) { +func (c *mongoGenericRepositoryTest) TearDownTest() { + err := c.cleanupMongoData() + c.Require().NoError(err) +} + +func (c *mongoGenericRepositoryTest) Test_Add() { ctx := context.Background() - repository, err := setupGenericMongoRepository(ctx, t) product := &ProductMongo{ - ID: uuid.NewV4(). - String(), // we generate id ourselves because auto generate mongo string id column with type _id is not an uuid - Name: "added_product", - Weight: 100, + ID: uuid.NewV4().String(), + Name: gofakeit.Name(), + Weight: gofakeit.Number(100, 1000), IsAvailable: true, } - err = repository.Add(ctx, product) - if err != nil { - t.Fatal(err) - } + err := c.productRepository.Add(ctx, product) + c.Require().NoError(err) id, err := uuid.FromString(product.ID) - if err != nil { - return - } + c.Require().NoError(err) - p, err := repository.GetById(ctx, id) - if err != nil { - return - } + p, err := c.productRepository.GetById(ctx, id) + c.Require().NoError(err) - assert.NotNil(t, p) - assert.Equal(t, product.ID, p.ID) + c.Assert().NotNil(p) + c.Assert().Equal(product.ID, p.ID) } -func Test_Add_With_Data_Model(t *testing.T) { +func (c *mongoGenericRepositoryTest) Test_Add_With_Data_Model() { ctx := context.Background() - repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) - if err != nil { - t.Fatal(err) - } - product := &Product{ - ID: uuid.NewV4(). - String(), + product := &ProductMongo{ // we generate id ourselves because auto generate mongo string id column with type _id is not an uuid - Name: "added_product", - Weight: 100, + ID: uuid.NewV4().String(), + Name: gofakeit.Name(), + Weight: gofakeit.Number(100, 1000), IsAvailable: true, } - err = repository.Add(ctx, product) - if err != nil { - t.Fatal(err) - } + err := c.productRepository.Add(ctx, product) + c.Require().NoError(err) id, err := uuid.FromString(product.ID) - if err != nil { - return - } + c.Require().NoError(err) - p, err := repository.GetById(ctx, id) - if err != nil { - return - } + p, err := c.productRepository.GetById(ctx, id) + c.Require().NoError(err) - assert.NotNil(t, p) - assert.Equal(t, product.ID, p.ID) + c.Assert().NotNil(p) + c.Assert().Equal(product.ID, p.ID) } -func Test_Get_By_Id(t *testing.T) { +func (c *mongoGenericRepositoryTest) Test_Get_By_Id() { ctx := context.Background() - repository, err := setupGenericMongoRepository(ctx, t) - if err != nil { - t.Fatal(err) - } - all, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - return - } + all, err := c.productRepository.GetAll(ctx, utils.NewListQuery(10, 1)) + c.Require().NoError(err) + p := all.Items[0] id, err := uuid.FromString(p.ID) + name := p.Name testCases := []struct { Name string @@ -138,7 +157,7 @@ func Test_Get_By_Id(t *testing.T) { ExpectResult *ProductMongo }{ { - Name: "ExistingProduct", + Name: name, ProductId: id, ExpectResult: p, }, @@ -149,12 +168,11 @@ func Test_Get_By_Id(t *testing.T) { }, } - for _, c := range testCases { - c := c - t.Run(c.Name, func(t *testing.T) { + for _, s := range testCases { + c.T().Run(s.Name, func(t *testing.T) { t.Parallel() - res, err := repository.GetById(ctx, c.ProductId) - if c.ExpectResult == nil { + res, err := c.productRepository.GetById(ctx, s.ProductId) + if s.ExpectResult == nil { assert.Error(t, err) assert.True(t, customErrors.IsNotFoundError(err)) assert.Nil(t, res) @@ -167,20 +185,18 @@ func Test_Get_By_Id(t *testing.T) { } } -func Test_Get_By_Id_With_Data_Model(t *testing.T) { +func (c *mongoGenericRepositoryTest) Test_Get_By_Id_With_Data_Model() { ctx := context.Background() - repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) - if err != nil { - t.Fatal(err) - } - all, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - return - } + all, err := c.productRepositoryWithDataModel.GetAll( + ctx, + utils.NewListQuery(10, 1), + ) + c.Require().NoError(err) p := all.Items[0] id, err := uuid.FromString(p.ID) + name := p.Name testCases := []struct { Name string @@ -188,7 +204,7 @@ func Test_Get_By_Id_With_Data_Model(t *testing.T) { ExpectResult *Product }{ { - Name: "ExistingProduct", + Name: name, ProductId: id, ExpectResult: p, }, @@ -199,12 +215,14 @@ func Test_Get_By_Id_With_Data_Model(t *testing.T) { }, } - for _, c := range testCases { - c := c - t.Run(c.Name, func(t *testing.T) { + for _, s := range testCases { + c.T().Run(s.Name, func(t *testing.T) { t.Parallel() - res, err := repository.GetById(ctx, c.ProductId) - if c.ExpectResult == nil { + res, err := c.productRepositoryWithDataModel.GetById( + ctx, + s.ProductId, + ) + if s.ExpectResult == nil { assert.Error(t, err) assert.True(t, customErrors.IsNotFoundError(err)) assert.Nil(t, res) @@ -217,394 +235,355 @@ func Test_Get_By_Id_With_Data_Model(t *testing.T) { } } -func Test_First_Or_Default(t *testing.T) { +func (c *mongoGenericRepositoryTest) Test_First_Or_Default() { ctx := context.Background() - repository, err := setupGenericMongoRepository(ctx, t) - if err != nil { - t.Fatal(err) - } - all, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - return - } + all, err := c.productRepository.GetAll(ctx, utils.NewListQuery(10, 1)) + c.Require().NoError(err) + p := all.Items[0] - single, err := repository.FirstOrDefault( + single, err := c.productRepository.FirstOrDefault( ctx, map[string]interface{}{"_id": p.ID}, ) - if err != nil { - t.Fatal(err) - } - assert.NotNil(t, single) + c.Require().NoError(err) + c.Assert().NotNil(single) } -func Test_First_Or_Default_With_Data_Model(t *testing.T) { +func (c *mongoGenericRepositoryTest) Test_First_Or_Default_With_Data_Model() { ctx := context.Background() - repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) - if err != nil { - t.Fatal(err) - } - all, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - return - } + all, err := c.productRepositoryWithDataModel.GetAll( + ctx, + utils.NewListQuery(10, 1), + ) + c.Require().NoError(err) + p := all.Items[0] - single, err := repository.FirstOrDefault( + single, err := c.productRepositoryWithDataModel.FirstOrDefault( ctx, map[string]interface{}{"_id": p.ID}, ) - if err != nil { - t.Fatal(err) - } - assert.NotNil(t, single) + + c.Require().NoError(err) + c.Assert().NotNil(single) } -func Test_Get_All(t *testing.T) { +func (c *mongoGenericRepositoryTest) Test_Get_All() { ctx := context.Background() - repository, err := setupGenericMongoRepository(ctx, t) - if err != nil { - t.Fatal(err) - } - models, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - t.Fatal(err) - } + models, err := c.productRepository.GetAll(ctx, utils.NewListQuery(10, 1)) + c.Require().NoError(err) - assert.NotEmpty(t, models.Items) + c.Assert().NotEmpty(models.Items) } -func Test_Get_All_With_Data_Model(t *testing.T) { +func (c *mongoGenericRepositoryTest) Test_Get_All_With_Data_Model() { ctx := context.Background() - repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) - if err != nil { - t.Fatal(err) - } - models, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - t.Fatal(err) - } + models, err := c.productRepositoryWithDataModel.GetAll( + ctx, + utils.NewListQuery(10, 1), + ) + c.Require().NoError(err) - assert.NotEmpty(t, models.Items) + c.Assert().NotEmpty(models.Items) } -func Test_Search(t *testing.T) { +func (c *mongoGenericRepositoryTest) Test_Search() { ctx := context.Background() - repository, err := setupGenericMongoRepository(ctx, t) - if err != nil { - t.Fatal(err) - } - models, err := repository.Search( + models, err := c.productRepository.Search( ctx, - "seed_product1", + c.products[0].Name, utils.NewListQuery(10, 1), ) - if err != nil { - t.Fatal(err) - } + c.Require().NoError(err) - assert.NotEmpty(t, models.Items) - assert.Equal(t, len(models.Items), 1) + c.Assert().NotEmpty(models.Items) + c.Assert().Equal(len(models.Items), 1) } -func Test_Search_With_Data_Model(t *testing.T) { +func (c *mongoGenericRepositoryTest) Test_Search_With_Data_Model() { ctx := context.Background() - repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) - models, err := repository.Search( + models, err := c.productRepositoryWithDataModel.Search( ctx, - "seed_product1", + c.products[0].Name, utils.NewListQuery(10, 1), ) - if err != nil { - t.Fatal(err) - } + c.Require().NoError(err) - assert.NotEmpty(t, models.Items) - assert.Equal(t, len(models.Items), 1) + c.Assert().NotEmpty(models.Items) + c.Assert().Equal(len(models.Items), 1) } -func Test_GetByFilter(t *testing.T) { +func (c *mongoGenericRepositoryTest) Test_GetByFilter() { ctx := context.Background() - repository, err := setupGenericMongoRepository(ctx, t) - models, err := repository.GetByFilter( + models, err := c.productRepository.GetByFilter( ctx, - map[string]interface{}{"name": "seed_product1"}, + map[string]interface{}{"name": c.products[0].Name}, ) - if err != nil { - t.Fatal(err) - } + c.Require().NoError(err) - assert.NotEmpty(t, models) - assert.Equal(t, len(models), 1) + c.Assert().NotEmpty(models) + c.Assert().Equal(len(models), 1) } -func Test_GetByFilter_With_Data_Model(t *testing.T) { +func (c *mongoGenericRepositoryTest) Test_GetByFilter_With_Data_Model() { ctx := context.Background() - repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) - models, err := repository.GetByFilter( + models, err := c.productRepositoryWithDataModel.GetByFilter( ctx, - map[string]interface{}{"name": "seed_product1"}, + map[string]interface{}{"name": c.products[0].Name}, ) - if err != nil { - t.Fatal(err) - } + c.Require().NoError(err) - assert.NotEmpty(t, models) - assert.Equal(t, len(models), 1) + c.Assert().NotEmpty(models) + c.Assert().Equal(len(models), 1) } -func Test_Update(t *testing.T) { +func (c *mongoGenericRepositoryTest) Test_Update() { ctx := context.Background() - repository, err := setupGenericMongoRepository(ctx, t) - products, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - t.Fatal(err) - } + products, err := c.productRepository.GetAll(ctx, utils.NewListQuery(10, 1)) + c.Require().NoError(err) + product := products.Items[0] product.Name = "product2_updated" - err = repository.Update(ctx, product) - if err != nil { - t.Fatal(err) - } + err = c.productRepository.Update(ctx, product) + c.Require().NoError(err) id, err := uuid.FromString(product.ID) - if err != nil { - t.Fatal(err) - } + c.Require().NoError(err) - single, err := repository.GetById(ctx, id) - if err != nil { - t.Fatal(err) - } - assert.NotNil(t, single) - assert.Equal(t, "product2_updated", single.Name) + single, err := c.productRepository.GetById(ctx, id) + c.Require().NoError(err) + + c.Assert().NotNil(single) + c.Assert().Equal("product2_updated", single.Name) } -func Test_Update_With_Data_Model(t *testing.T) { +func (c *mongoGenericRepositoryTest) Test_Update_With_Data_Model() { ctx := context.Background() - repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) - products, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - t.Fatal(err) - } + products, err := c.productRepositoryWithDataModel.GetAll( + ctx, + utils.NewListQuery(10, 1), + ) + c.Require().NoError(err) + product := products.Items[0] product.Name = "product2_updated" - err = repository.Update(ctx, product) - if err != nil { - t.Fatal(err) - } + err = c.productRepositoryWithDataModel.Update(ctx, product) + c.Require().NoError(err) id, err := uuid.FromString(product.ID) - if err != nil { - t.Fatal(err) - } - - single, err := repository.GetById(ctx, id) - if err != nil { - t.Fatal(err) - } - assert.NotNil(t, single) - assert.Equal(t, "product2_updated", single.Name) -} + c.Require().NoError(err) -func Test_Delete(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericMongoRepository(ctx, t) - - products, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - t.Fatal(err) - } - product := products.Items[0] - - id, err := uuid.FromString(product.ID) - if err != nil { - t.Fatal(err) - } - - err = repository.Delete(ctx, id) - if err != nil { - return - } + single, err := c.productRepositoryWithDataModel.GetById(ctx, id) + c.Require().NoError(err) - single, err := repository.GetById(ctx, id) - assert.Nil(t, single) + c.Assert().NotNil(single) + c.Assert().Equal("product2_updated", single.Name) } -func Test_Delete_With_Data_Model(t *testing.T) { +func (c *mongoGenericRepositoryTest) Test_Delete() { ctx := context.Background() - repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) - products, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) - if err != nil { - t.Fatal(err) - } + products, err := c.productRepository.GetAll(ctx, utils.NewListQuery(10, 1)) + c.Require().NoError(err) + product := products.Items[0] id, err := uuid.FromString(product.ID) - if err != nil { - t.Fatal(err) - } - - err = repository.Delete(ctx, id) - if err != nil { - return - } - - single, err := repository.GetById(ctx, id) - assert.Nil(t, single) -} - -func Test_Count(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericMongoRepository(ctx, t) - if err != nil { - t.Fatal(err) - } - - count := repository.Count(ctx) - assert.Equal(t, count, int64(2)) -} + c.Require().NoError(err) -func Test_Count_With_Data_Model(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) - if err != nil { - t.Fatal(err) - } + err = c.productRepository.Delete(ctx, id) + c.Require().NoError(err) - count := repository.Count(ctx) - assert.Equal(t, count, int64(2)) + single, err := c.productRepository.GetById(ctx, id) + c.Assert().Nil(single) } -func Test_Skip_Take(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericMongoRepository(ctx, t) - if err != nil { - t.Fatal(err) - } - - entities, err := repository.SkipTake(ctx, 1, 1) - if err != nil { - t.Fatal(err) - } - - assert.Equal(t, len(entities), 1) -} - -func Test_Skip_Take_With_Data_Model(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) - if err != nil { - t.Fatal(err) - } - - entities, err := repository.SkipTake(ctx, 1, 1) - if err != nil { - t.Fatal(err) - } - - assert.Equal(t, len(entities), 1) -} - -func Test_Find(t *testing.T) { - ctx := context.Background() - repository, err := setupGenericMongoRepository(ctx, t) - if err != nil { - t.Fatal(err) - } - - entities, err := repository.Find( - ctx, - specification.And( - specification.Equal("is_available", true), - specification.Equal("name", "seed_product1"), - ), +//func Test_Delete_With_Data_Model(t *testing.T) { +// ctx := context.Background() +// repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) +// +// products, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) +// if err != nil { +// t.Fatal(err) +// } +// product := products.Items[0] +// +// id, err := uuid.FromString(product.ID) +// if err != nil { +// t.Fatal(err) +// } +// +// err = repository.Delete(ctx, id) +// if err != nil { +// return +// } +// +// single, err := repository.GetById(ctx, id) +// assert.Nil(t, single) +//} +// +//func Test_Count(t *testing.T) { +// ctx := context.Background() +// repository, err := setupGenericMongoRepository(ctx, t) +// if err != nil { +// t.Fatal(err) +// } +// +// count := repository.Count(ctx) +// assert.Equal(t, count, int64(2)) +//} +// +//func Test_Count_With_Data_Model(t *testing.T) { +// ctx := context.Background() +// repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) +// if err != nil { +// t.Fatal(err) +// } +// +// count := repository.Count(ctx) +// assert.Equal(t, count, int64(2)) +//} +// +//func Test_Skip_Take(t *testing.T) { +// ctx := context.Background() +// repository, err := setupGenericMongoRepository(ctx, t) +// if err != nil { +// t.Fatal(err) +// } +// +// entities, err := repository.SkipTake(ctx, 1, 1) +// if err != nil { +// t.Fatal(err) +// } +// +// assert.Equal(t, len(entities), 1) +//} +// +//func Test_Skip_Take_With_Data_Model(t *testing.T) { +// ctx := context.Background() +// repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) +// if err != nil { +// t.Fatal(err) +// } +// +// entities, err := repository.SkipTake(ctx, 1, 1) +// if err != nil { +// t.Fatal(err) +// } +// +// assert.Equal(t, len(entities), 1) +//} +// +//func Test_Find(t *testing.T) { +// ctx := context.Background() +// repository, err := setupGenericMongoRepository(ctx, t) +// if err != nil { +// t.Fatal(err) +// } +// +// entities, err := repository.Find( +// ctx, +// specification.And( +// specification.Equal("is_available", true), +// specification.Equal("name", "seed_product1"), +// ), +// ) +// if err != nil { +// return +// } +// assert.Equal(t, len(entities), 1) +//} +// +//func Test_Find_With_Data_Model(t *testing.T) { +// ctx := context.Background() +// repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) +// if err != nil { +// t.Fatal(err) +// } +// +// entities, err := repository.Find( +// ctx, +// specification.And( +// specification.Equal("is_available", true), +// specification.Equal("name", "seed_product1"), +// ), +// ) +// if err != nil { +// return +// } +// assert.Equal(t, len(entities), 1) +//} +// +//func setupGenericMongoRepositoryWithDataModel( +// ctx context.Context, +// t *testing.T, +//) (data.GenericRepositoryWithDataModel[*ProductMongo, *Product], error) { +// db, err := mongocontainer.NewMongoTestContainers(defaultLogger.GetLogger()). +// Start(ctx, t) +// if err != nil { +// return nil, err +// } +// +// err = seedData(ctx, db) +// if err != nil { +// return nil, err +// } +// +// return NewGenericMongoRepositoryWithDataModel[*ProductMongo, *Product]( +// db, +// DatabaseName, +// CollectionName, +// ), nil +//} + +func (c *mongoGenericRepositoryTest) cleanupMongoData() error { + collections := []string{c.collectionName} + err := cleanupCollections( + c.mongoClient, + collections, + c.databaseName, ) - if err != nil { - return - } - assert.Equal(t, len(entities), 1) + + return err } -func Test_Find_With_Data_Model(t *testing.T) { +func cleanupCollections( + db *mongo.Client, + collections []string, + databaseName string, +) error { + database := db.Database(databaseName) ctx := context.Background() - repository, err := setupGenericMongoRepositoryWithDataModel(ctx, t) - if err != nil { - t.Fatal(err) - } - - entities, err := repository.Find( - ctx, - specification.And( - specification.Equal("is_available", true), - specification.Equal("name", "seed_product1"), - ), - ) - if err != nil { - return - } - assert.Equal(t, len(entities), 1) -} -func setupGenericMongoRepositoryWithDataModel( - ctx context.Context, - t *testing.T, -) (data.GenericRepositoryWithDataModel[*ProductMongo, *Product], error) { - db, err := mongo2.NewMongoTestContainers(defaultLogger.GetLogger()). - Start(ctx, t) - if err != nil { - return nil, err - } + // Iterate over the collections and delete all collections + for _, collection := range collections { + collection := database.Collection(collection) - err = seedAndMigration(ctx, db) - if err != nil { - return nil, err + err := collection.Drop(ctx) + if err != nil { + return err + } } - return NewGenericMongoRepositoryWithDataModel[*ProductMongo, *Product]( - db, - DatabaseName, - CollectionName, - ), nil + return nil } -func setupGenericMongoRepository( +func (c *mongoGenericRepositoryTest) seedData( ctx context.Context, - t *testing.T, -) (data.GenericRepository[*ProductMongo], error) { - db, err := mongo2.NewMongoTestContainers(defaultLogger.GetLogger()). - Start(ctx, t) - if err != nil { - return nil, err - } - - err = seedAndMigration(ctx, db) - if err != nil { - return nil, err - } - - return NewGenericMongoRepository[*ProductMongo]( - db, - DatabaseName, - CollectionName, - ), nil -} - -func seedAndMigration(ctx context.Context, db *mongo.Client) error { +) ([]*ProductMongo, error) { seedProducts := []*ProductMongo{ { ID: uuid.NewV4(). @@ -630,11 +609,12 @@ func seedAndMigration(ctx context.Context, db *mongo.Client) error { data[i] = v } - collection := db.Database(DatabaseName).Collection(CollectionName) + collection := c.mongoClient.Database(c.databaseName). + Collection(c.collectionName) _, err := collection.InsertMany(ctx, data, &options.InsertManyOptions{}) if err != nil { - return err + return nil, err } - return nil + return seedProducts, nil } diff --git a/internal/pkg/otel/constants/telemetry_attributes/app/app.go b/internal/pkg/otel/constants/telemetry_attributes/app/app.go deleted file mode 100644 index cf48edc5..00000000 --- a/internal/pkg/otel/constants/telemetry_attributes/app/app.go +++ /dev/null @@ -1,26 +0,0 @@ -package app - -const ( - DefaultSourceName = "app" - Consumer = "app.consumer" - EventHandler = "app.event-handler" - Subscription = "app.subscription" - Stream = "app.stream" - Partition = "app.partition" - Request = "app.request" - RequestName = "app.request_name" - RequestResultName = "app.request_result_name" - RequestResult = "app.request_result" - Command = "app.command" - CommandName = "app.command_name" - CommandResult = "app.command_result" - CommandResultName = "app.command_result_name" - Query = "app.query" - QueryName = "app.query_name" - QueryResult = "app.query_result" - QueryResultName = "app.query_result_name" - Event = "app.event" - EventName = "app.event_name" - EventResult = "app.event_result" - EventResultName = "app.event_result_name" -) diff --git a/internal/pkg/otel/constants/telemetry_attributes/exception/exception.go b/internal/pkg/otel/constants/telemetry_attributes/exception/exception.go deleted file mode 100644 index 4124a08a..00000000 --- a/internal/pkg/otel/constants/telemetry_attributes/exception/exception.go +++ /dev/null @@ -1,8 +0,0 @@ -package exception - -const ( - EventName = "exception" - Type = "exception.type" - Message = "exception.message" - Stacktrace = "exception.stacktrace" -) diff --git a/internal/pkg/otel/constants/telemetry_attributes/general/general.go b/internal/pkg/otel/constants/telemetry_attributes/general/general.go deleted file mode 100644 index 5bbe309c..00000000 --- a/internal/pkg/otel/constants/telemetry_attributes/general/general.go +++ /dev/null @@ -1 +0,0 @@ -package general diff --git a/internal/pkg/otel/constants/telemetry_attributes/grpc/grpc.go b/internal/pkg/otel/constants/telemetry_attributes/grpc/grpc.go deleted file mode 100644 index 16cf53c6..00000000 --- a/internal/pkg/otel/constants/telemetry_attributes/grpc/grpc.go +++ /dev/null @@ -1,3 +0,0 @@ -package grpc - -// https://opentelemetry.io/docs/specs/otel/trace/semantic_conventions/rpc/ diff --git a/internal/pkg/otel/constants/telemetry_attributes/messaging/messaging.go b/internal/pkg/otel/constants/telemetry_attributes/messaging/messaging.go deleted file mode 100644 index af5528e0..00000000 --- a/internal/pkg/otel/constants/telemetry_attributes/messaging/messaging.go +++ /dev/null @@ -1,14 +0,0 @@ -package messaging - -// https://opentelemetry.io/docs/specs/otel/trace/semantic_conventions/messaging/ -const ( - System = "messaging.system" - Destination = "messaging.destination" - DestinationKind = "messaging.destination_kind" - Url = "messaging.url" - MessageId = "messaging.message_id" - ConversationId = "messaging.conversation_id" - CorrelationId = "messaging.correlation_id" - CausationId = "messaging.causation_id" - Operation = "messaging.operation" -) diff --git a/internal/pkg/otel/constants/telemetry_attributes/net/net.go b/internal/pkg/otel/constants/telemetry_attributes/net/net.go deleted file mode 100644 index b5e7cfcb..00000000 --- a/internal/pkg/otel/constants/telemetry_attributes/net/net.go +++ /dev/null @@ -1,11 +0,0 @@ -package net - -const ( - Transport = "net.transport" - PeerIp = "net.peer.ip" - PeerPort = "net.peer.port" - PeerName = "net.peer.name" - HostIp = "net.host.ip" - HostPort = "net.host.port" - HostName = "net.host.name" -) diff --git a/internal/pkg/otel/constants/telemetrytags/telemetrytags.go b/internal/pkg/otel/constants/telemetrytags/telemetrytags.go new file mode 100644 index 00000000..ec1982e8 --- /dev/null +++ b/internal/pkg/otel/constants/telemetrytags/telemetrytags.go @@ -0,0 +1,119 @@ +package telemetrytags + +type app struct { + DefaultSourceName string + Consumer string + EventHandler string + Subscription string + Stream string + Partition string + Request string + RequestName string + RequestResultName string + RequestResult string + Command string + CommandName string + CommandResult string + CommandResultName string + Query string + QueryName string + QueryResult string + QueryResultName string + Event string + EventName string + EventResult string + EventResultName string +} + +// https://opentelemetry.io/docs/specs/otel/trace/semantic_conventions/messaging/ +type messaging struct { + System string + Destination string + DestinationKind string + Url string + MessageId string + ConversationId string + CorrelationId string + CausationId string + Operation string +} + +type exceptions struct { + EventName string + Type string + Message string + Stacktrace string +} + +type general struct{} + +// https://opentelemetry.io/docs/specs/otel/trace/semantic_conventions/rpc/ +type grpc struct{} + +type netHttp struct { + Transport string + PeerIp string + PeerPort string + PeerName string + HostIp string + HostPort string + HostName string +} + +var App = app{ + DefaultSourceName: "app", + Consumer: "app.consumer", + EventHandler: "app.event-handler", + Subscription: "app.subscription", + Stream: "app.stream", + Partition: "app.partition", + Request: "app.request", + RequestName: "app.request_name", + RequestResultName: "app.request_result_name", + RequestResult: "app.request_result", + Command: "app.command", + CommandName: "app.command_name", + CommandResult: "app.command_result", + CommandResultName: "app.command_result_name", + Query: "app.query", + QueryName: "app.query_name", + QueryResult: "app.query_result", + QueryResultName: "app.query_result_name", + Event: "app.event", + EventName: "app.event_name", + EventResult: "app.event_result", + EventResultName: "app.event_result_name", +} + +var Exceptions = exceptions{ + EventName: "exception", + Type: "exception.type", + Message: "exception.message", + Stacktrace: "exception.stacktrace", +} + +var General = general{} + +var Grpc = grpc{} + +var Messaging = messaging{ + System: "messaging.system", + Destination: "messaging.destination", + DestinationKind: "messaging.destination_kind", + Url: "messaging.url", + MessageId: "messaging.message_id", + ConversationId: "messaging.conversation_id", + CorrelationId: "messaging.correlation_id", + CausationId: "messaging.causation_id", + Operation: "messaging.operation", +} + +var NetHttp = netHttp{ + Transport: "net.transport", + PeerIp: "net.peer.ip", + PeerPort: "net.peer.port", + PeerName: "net.peer.name", + HostIp: "net.host.ip", + HostPort: "net.host.port", + HostName: "net.host.name", +} diff --git a/internal/pkg/otel/metrics/mediatr/pipelines/config.go b/internal/pkg/otel/metrics/mediatr/pipelines/config.go index e344c53d..03812b0b 100644 --- a/internal/pkg/otel/metrics/mediatr/pipelines/config.go +++ b/internal/pkg/otel/metrics/mediatr/pipelines/config.go @@ -2,7 +2,7 @@ package pipelines import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" ) type config struct { diff --git a/internal/pkg/otel/metrics/mediatr/pipelines/mediator_metrics_pipeline.go b/internal/pkg/otel/metrics/mediatr/pipelines/mediator_metrics_pipeline.go index 4e83b4ab..03e7a5e9 100644 --- a/internal/pkg/otel/metrics/mediatr/pipelines/mediator_metrics_pipeline.go +++ b/internal/pkg/otel/metrics/mediatr/pipelines/mediator_metrics_pipeline.go @@ -6,10 +6,10 @@ import ( "strings" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants/telemetry_attributes/app" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants/telemetrytags" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" - attribute2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + customAttribute "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + typemapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/mehdihadeli/go-mediatr" "go.opentelemetry.io/otel/attribute" @@ -41,32 +41,32 @@ func (r *mediatorMetricsPipeline) Handle( request interface{}, next mediatr.RequestHandlerFunc, ) (interface{}, error) { - requestName := typeMapper.GetSnakeTypeName(request) + requestName := typemapper.GetSnakeTypeName(request) - requestNameAttribute := app.RequestName - requestAttribute := app.Request - requestResultName := app.RequestResultName - requestResult := app.RequestResult + requestNameTag := telemetrytags.App.RequestName + requestTag := telemetrytags.App.Request + requestResultNameTag := telemetrytags.App.RequestResultName + requestResultTag := telemetrytags.App.RequestResult requestType := "request" switch { - case strings.Contains(typeMapper.GetPackageName(request), "command") || strings.Contains(typeMapper.GetPackageName(request), "commands"): - requestNameAttribute = app.CommandName - requestAttribute = app.Command - requestResultName = app.CommandResultName - requestResult = app.CommandResult + case strings.Contains(typemapper.GetPackageName(request), "command") || strings.Contains(typemapper.GetPackageName(request), "commands"): + requestNameTag = telemetrytags.App.CommandName + requestTag = telemetrytags.App.Command + requestResultNameTag = telemetrytags.App.CommandResultName + requestResultTag = telemetrytags.App.CommandResult requestType = "command" - case strings.Contains(typeMapper.GetPackageName(request), "query") || strings.Contains(typeMapper.GetPackageName(request), "queries"): - requestNameAttribute = app.QueryName - requestAttribute = app.Query - requestResultName = app.QueryResultName - requestResult = app.QueryResult + case strings.Contains(typemapper.GetPackageName(request), "query") || strings.Contains(typemapper.GetPackageName(request), "queries"): + requestNameTag = telemetrytags.App.QueryName + requestTag = telemetrytags.App.Query + requestResultNameTag = telemetrytags.App.QueryResultName + requestResultTag = telemetrytags.App.QueryResult requestType = "query" - case strings.Contains(typeMapper.GetPackageName(request), "event") || strings.Contains(typeMapper.GetPackageName(request), "events"): - requestNameAttribute = app.EventName - requestAttribute = app.Event - requestResultName = app.EventResultName - requestResult = app.EventResult + case strings.Contains(typemapper.GetPackageName(request), "event") || strings.Contains(typemapper.GetPackageName(request), "events"): + requestNameTag = telemetrytags.App.EventName + requestTag = telemetrytags.App.Event + requestResultNameTag = telemetrytags.App.EventResultName + requestResultTag = telemetrytags.App.EventResult requestType = "event" } @@ -138,12 +138,14 @@ func (r *mediatorMetricsPipeline) Handle( // Calculate the duration duration := time.Since(startTime).Milliseconds() - responseName := typeMapper.GetSnakeTypeName(response) + // response will be nil if we have an error + responseName := typemapper.GetSnakeTypeName(response) + opt := metric.WithAttributes( - attribute.String(requestNameAttribute, requestName), - attribute2.Object(requestAttribute, request), - attribute.String(requestResultName, responseName), - attribute2.Object(requestResult, response), + attribute.String(requestNameTag, requestName), + customAttribute.Object(requestTag, request), + attribute.String(requestResultNameTag, responseName), + customAttribute.Object(requestResultTag, response), ) // Record metrics diff --git a/internal/pkg/otel/metrics/messaging/pipeline/config.go b/internal/pkg/otel/metrics/messaging/pipeline/config.go index e344c53d..03812b0b 100644 --- a/internal/pkg/otel/metrics/messaging/pipeline/config.go +++ b/internal/pkg/otel/metrics/messaging/pipeline/config.go @@ -2,7 +2,7 @@ package pipelines import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" ) type config struct { diff --git a/internal/pkg/otel/metrics/messaging/pipeline/messaging_metrics_pipeline.go b/internal/pkg/otel/metrics/messaging/pipeline/messaging_metrics_pipeline.go index 049122f8..b11a461c 100644 --- a/internal/pkg/otel/metrics/messaging/pipeline/messaging_metrics_pipeline.go +++ b/internal/pkg/otel/metrics/messaging/pipeline/messaging_metrics_pipeline.go @@ -5,11 +5,11 @@ import ( "fmt" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/pipeline" - types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/pipeline" + types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" attribute2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" diff --git a/internal/pkg/otel/metrics/metrics_options.go b/internal/pkg/otel/metrics/metrics_options.go index 07ca912e..62a50a78 100644 --- a/internal/pkg/otel/metrics/metrics_options.go +++ b/internal/pkg/otel/metrics/metrics_options.go @@ -3,7 +3,7 @@ package metrics import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/iancoleman/strcase" ) diff --git a/internal/pkg/otel/tracing/mediatr/pipelines/config.go b/internal/pkg/otel/tracing/mediatr/pipelines/config.go index e344c53d..03812b0b 100644 --- a/internal/pkg/otel/tracing/mediatr/pipelines/config.go +++ b/internal/pkg/otel/tracing/mediatr/pipelines/config.go @@ -2,7 +2,7 @@ package pipelines import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" ) type config struct { diff --git a/internal/pkg/otel/tracing/mediatr/pipelines/mediator_tracing_pipeline.go b/internal/pkg/otel/tracing/mediatr/pipelines/mediator_tracing_pipeline.go index 5691cb89..f5ac39a7 100644 --- a/internal/pkg/otel/tracing/mediatr/pipelines/mediator_tracing_pipeline.go +++ b/internal/pkg/otel/tracing/mediatr/pipelines/mediator_tracing_pipeline.go @@ -5,14 +5,13 @@ import ( "fmt" "strings" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants/telemetry_attributes/app" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants/telemetrytags" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants/tracing/components" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - attribute2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" + customAttribute "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" - "emperror.dev/errors" "github.com/mehdihadeli/go-mediatr" "go.opentelemetry.io/otel/attribute" ) @@ -45,30 +44,30 @@ func (r *mediatorTracingPipeline) Handle( requestName := typeMapper.GetSnakeTypeName(request) componentName := components.RequestHandler - requestNameAttribute := app.RequestName - requestAttribute := app.Request - requestResultName := app.RequestResultName - requestResult := app.RequestResult + requestNameTag := telemetrytags.App.RequestName + requestTag := telemetrytags.App.Request + requestResultNameTag := telemetrytags.App.RequestResultName + requestResultTag := telemetrytags.App.RequestResult switch { case strings.Contains(typeMapper.GetPackageName(request), "command") || strings.Contains(typeMapper.GetPackageName(request), "commands"): componentName = components.CommandHandler - requestNameAttribute = app.CommandName - requestAttribute = app.Command - requestResultName = app.CommandResultName - requestResult = app.CommandResult + requestNameTag = telemetrytags.App.CommandName + requestTag = telemetrytags.App.Command + requestResultNameTag = telemetrytags.App.CommandResultName + requestResultTag = telemetrytags.App.CommandResult case strings.Contains(typeMapper.GetPackageName(request), "query") || strings.Contains(typeMapper.GetPackageName(request), "queries"): componentName = components.QueryHandler - requestNameAttribute = app.QueryName - requestAttribute = app.Query - requestResultName = app.QueryResultName - requestResult = app.QueryResult + requestNameTag = telemetrytags.App.QueryName + requestTag = telemetrytags.App.Query + requestResultNameTag = telemetrytags.App.QueryResultName + requestResultTag = telemetrytags.App.QueryResult case strings.Contains(typeMapper.GetPackageName(request), "event") || strings.Contains(typeMapper.GetPackageName(request), "events"): componentName = components.EventHandler - requestNameAttribute = app.EventName - requestAttribute = app.Event - requestResultName = app.EventResultName - requestResult = app.EventResult + requestNameTag = telemetrytags.App.EventName + requestTag = telemetrytags.App.Event + requestResultNameTag = telemetrytags.App.EventResultName + requestResultTag = telemetrytags.App.EventResult } operationName := fmt.Sprintf("%s_handler", requestName) @@ -85,24 +84,21 @@ func (r *mediatorTracingPipeline) Handle( defer span.End() span.SetAttributes( - attribute.String(requestNameAttribute, requestName), - attribute2.Object(requestAttribute, request), + attribute.String(requestNameTag, requestName), + customAttribute.Object(requestTag, request), ) response, err := next(newCtx) responseName := typeMapper.GetSnakeTypeName(response) span.SetAttributes( - attribute.String(requestResultName, responseName), - attribute2.Object(requestResult, response), + attribute.String(requestResultNameTag, responseName), + customAttribute.Object(requestResultTag, response), ) err = utils.TraceStatusFromSpan( span, - errors.WrapIf( - err, - fmt.Sprintf("Request '%s' failed.", requestName), - ), + err, ) return response, err diff --git a/internal/pkg/otel/tracing/tracing_options.go b/internal/pkg/otel/tracing/tracing_options.go index 276e0e06..a72c26f0 100644 --- a/internal/pkg/otel/tracing/tracing_options.go +++ b/internal/pkg/otel/tracing/tracing_options.go @@ -3,7 +3,7 @@ package tracing import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/iancoleman/strcase" ) diff --git a/internal/pkg/otel/tracing/utils/utils.go b/internal/pkg/otel/tracing/utils/utils.go index f36ed0b5..ff03dfb9 100644 --- a/internal/pkg/otel/tracing/utils/utils.go +++ b/internal/pkg/otel/tracing/utils/utils.go @@ -9,7 +9,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/grpcErrors" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/problemDetails" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants/telemetry_attributes/exception" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants/telemetrytags" errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" "github.com/ahmetb/go-linq/v3" @@ -64,8 +64,8 @@ func HttpTraceStatusFromSpan(span trace.Span, err error) error { // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors span.SetAttributes( - attribute.String(exception.Message, err.Error()), - attribute.String(exception.Stacktrace, stackTraceError), + attribute.String(telemetrytags.Exceptions.Message, err.Error()), + attribute.String(telemetrytags.Exceptions.Stacktrace, stackTraceError), ) span.RecordError(err) } @@ -95,8 +95,8 @@ func TraceStatusFromSpan(span trace.Span, err error) error { // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors span.SetAttributes( - attribute.String(exception.Message, err.Error()), - attribute.String(exception.Stacktrace, stackTraceError), + attribute.String(telemetrytags.Exceptions.Message, err.Error()), + attribute.String(telemetrytags.Exceptions.Stacktrace, stackTraceError), ) span.RecordError(err) } @@ -114,8 +114,8 @@ func TraceErrStatusFromSpan(span trace.Span, err error) error { // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors span.SetAttributes( - attribute.String(exception.Message, err.Error()), - attribute.String(exception.Stacktrace, stackTraceError), + attribute.String(telemetrytags.Exceptions.Message, err.Error()), + attribute.String(telemetrytags.Exceptions.Stacktrace, stackTraceError), ) span.RecordError(err) } @@ -134,8 +134,8 @@ func HttpTraceStatusFromSpanWithCode( // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors span.SetAttributes( - attribute.String(exception.Message, err.Error()), - attribute.String(exception.Stacktrace, stackTraceError), + attribute.String(telemetrytags.Exceptions.Message, err.Error()), + attribute.String(telemetrytags.Exceptions.Stacktrace, stackTraceError), ) span.RecordError(err) } @@ -193,8 +193,8 @@ func GrpcTraceErrFromSpan(span trace.Span, err error) error { stackTraceError := errorUtils.ErrorsWithStack(err) // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors span.SetAttributes( - attribute.String(exception.Message, err.Error()), - attribute.String(exception.Stacktrace, stackTraceError), + attribute.String(telemetrytags.Exceptions.Message, err.Error()), + attribute.String(telemetrytags.Exceptions.Stacktrace, stackTraceError), ) if customErrors.IsCustomError(err) { @@ -220,8 +220,8 @@ func GrpcTraceErrFromSpanWithCode(span trace.Span, err error, code int) error { stackTraceError := errorUtils.ErrorsWithStack(err) // https://opentelemetry.io/docs/instrumentation/go/manual/#record-errors span.SetAttributes( - attribute.String(exception.Message, err.Error()), - attribute.String(exception.Stacktrace, stackTraceError), + attribute.String(telemetrytags.Exceptions.Message, err.Error()), + attribute.String(telemetrytags.Exceptions.Stacktrace, stackTraceError), ) span.SetAttributes(semconv.RPCGRPCStatusCodeKey.Int(code)) span.RecordError(err) diff --git a/internal/pkg/postgresGorm/constants/constants.go b/internal/pkg/postgresGorm/constants/constants.go new file mode 100644 index 00000000..d45da51a --- /dev/null +++ b/internal/pkg/postgresGorm/constants/constants.go @@ -0,0 +1,5 @@ +package constants + +type contextKey string + +const TxKey contextKey = "tx_key" diff --git a/internal/pkg/postgresGorm/contracts/gorm_context.go b/internal/pkg/postgresGorm/contracts/gorm_context.go new file mode 100644 index 00000000..3acbd734 --- /dev/null +++ b/internal/pkg/postgresGorm/contracts/gorm_context.go @@ -0,0 +1,12 @@ +package contracts + +import ( + "context" + + "gorm.io/gorm" +) + +type GormContext struct { + Tx *gorm.DB + context.Context +} diff --git a/internal/pkg/gorm_postgres/db.go b/internal/pkg/postgresGorm/db.go similarity index 56% rename from internal/pkg/gorm_postgres/db.go rename to internal/pkg/postgresGorm/db.go index fa85fdf3..0e147cf3 100644 --- a/internal/pkg/gorm_postgres/db.go +++ b/internal/pkg/postgresGorm/db.go @@ -1,14 +1,14 @@ -package gormPostgres +package postgresGorm import ( "database/sql" "fmt" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" + defaultlogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/gromlog" "emperror.dev/errors" - "github.com/uptrace/bun/driver/pgdriver" + "github.com/glebarez/sqlite" gormPostgres "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/plugin/opentelemetry/tracing" @@ -24,8 +24,13 @@ func NewGorm(cfg *GormOptions) (*gorm.DB, error) { return nil, err } - var dataSourceName string - dataSourceName = fmt.Sprintf( + if cfg.UseInMemory { + db, err := createInMemoryDB() + + return db, err + } + + dataSourceName := fmt.Sprintf( "host=%s port=%d user=%s dbname=%s password=%s", cfg.Host, cfg.Port, @@ -37,7 +42,7 @@ func NewGorm(cfg *GormOptions) (*gorm.DB, error) { gormDb, err := gorm.Open( gormPostgres.Open(dataSourceName), &gorm.Config{ - Logger: gromlog.NewGormCustomLogger(defaultLogger.GetLogger()), + Logger: gromlog.NewGormCustomLogger(defaultlogger.GetLogger()), }, ) if err != nil { @@ -52,22 +57,49 @@ func NewGorm(cfg *GormOptions) (*gorm.DB, error) { return gormDb, nil } +func createInMemoryDB() (*gorm.DB, error) { + // https://gorm.io/docs/connecting_to_the_database.html#SQLite + // https://github.com/glebarez/sqlite + // https://www.connectionstrings.com/sqlite/ + db, err := gorm.Open( + sqlite.Open(":memory:"), + &gorm.Config{ + Logger: gromlog.NewGormCustomLogger(defaultlogger.GetLogger()), + }) + return db, err +} + func NewSQLDB(orm *gorm.DB) (*sql.DB, error) { return orm.DB() } func createDB(cfg *GormOptions) error { + var db *sql.DB + // we should choose a default database in the connection, but because we don't have a database yet we specify postgres default database 'postgres' - datasource := fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=disable", - cfg.User, - cfg.Password, + dataSourceName := fmt.Sprintf( + "host=%s port=%d user=%s dbname=%s password=%s", cfg.Host, cfg.Port, + cfg.User, "postgres", + cfg.Password, ) + postgresGormDB, err := gorm.Open( + gormPostgres.Open(dataSourceName), + &gorm.Config{ + Logger: gromlog.NewGormCustomLogger(defaultlogger.GetLogger()), + }, + ) + if err != nil { + return err + } - sqldb := sql.OpenDB(pgdriver.NewConnector(pgdriver.WithDSN(datasource))) + db, err = postgresGormDB.DB() - var exists int - rows, err := sqldb.Query( + if err != nil { + return err + } + + rows, err := db.Query( fmt.Sprintf( "SELECT 1 FROM pg_catalog.pg_database WHERE datname='%s'", cfg.DBName, @@ -77,6 +109,7 @@ func createDB(cfg *GormOptions) error { return err } + var exists int if rows.Next() { err = rows.Scan(&exists) if err != nil { @@ -88,12 +121,12 @@ func createDB(cfg *GormOptions) error { return nil } - _, err = sqldb.Exec(fmt.Sprintf("CREATE DATABASE %s", cfg.DBName)) + _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", cfg.DBName)) if err != nil { return err } - defer sqldb.Close() + defer db.Close() return nil } diff --git a/internal/pkg/gorm_postgres/gorm_options.go b/internal/pkg/postgresGorm/gorm_options.go similarity index 90% rename from internal/pkg/gorm_postgres/gorm_options.go rename to internal/pkg/postgresGorm/gorm_options.go index eb414c63..b9c04226 100644 --- a/internal/pkg/gorm_postgres/gorm_options.go +++ b/internal/pkg/postgresGorm/gorm_options.go @@ -1,11 +1,11 @@ -package gormPostgres +package postgresGorm import ( "fmt" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/iancoleman/strcase" ) @@ -13,6 +13,7 @@ import ( var optionName = strcase.ToLowerCamel(typeMapper.GetTypeNameByT[GormOptions]()) type GormOptions struct { + UseInMemory bool `mapstructure:"useInMemory"` Host string `mapstructure:"host"` Port int `mapstructure:"port"` User string `mapstructure:"user"` diff --git a/internal/pkg/gorm_postgres/gorm_options_test.go b/internal/pkg/postgresGorm/gorm_options_test.go similarity index 87% rename from internal/pkg/gorm_postgres/gorm_options_test.go rename to internal/pkg/postgresGorm/gorm_options_test.go index 3240d833..b8ead84f 100644 --- a/internal/pkg/gorm_postgres/gorm_options_test.go +++ b/internal/pkg/postgresGorm/gorm_options_test.go @@ -1,4 +1,4 @@ -package gormPostgres +package postgresGorm import ( "testing" diff --git a/internal/pkg/gorm_postgres/gorm_postgres_fx.go b/internal/pkg/postgresGorm/gorm_postgres_fx.go similarity index 95% rename from internal/pkg/gorm_postgres/gorm_postgres_fx.go rename to internal/pkg/postgresGorm/gorm_postgres_fx.go index c61a4038..e7c9b253 100644 --- a/internal/pkg/gorm_postgres/gorm_postgres_fx.go +++ b/internal/pkg/postgresGorm/gorm_postgres_fx.go @@ -1,4 +1,4 @@ -package gormPostgres +package postgresGorm import ( "fmt" diff --git a/internal/pkg/gorm_postgres/health.go b/internal/pkg/postgresGorm/health.go similarity index 95% rename from internal/pkg/gorm_postgres/health.go rename to internal/pkg/postgresGorm/health.go index 4d1f177d..717e5702 100644 --- a/internal/pkg/gorm_postgres/health.go +++ b/internal/pkg/postgresGorm/health.go @@ -1,4 +1,4 @@ -package gormPostgres +package postgresGorm import ( "context" diff --git a/internal/pkg/gorm_postgres/helpers.go b/internal/pkg/postgresGorm/helpers.go similarity index 57% rename from internal/pkg/gorm_postgres/helpers.go rename to internal/pkg/postgresGorm/helpers.go index 1e19bad2..7b1c070a 100644 --- a/internal/pkg/gorm_postgres/helpers.go +++ b/internal/pkg/postgresGorm/helpers.go @@ -1,10 +1,11 @@ -package gormPostgres +package postgresGorm import ( "context" "fmt" "strings" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "emperror.dev/errors" @@ -13,17 +14,23 @@ import ( // Ref: https://dev.to/rafaelgfirmino/pagination-using-gorm-scopes-3k5f -func Paginate[T any]( +func Paginate[TDataModel any, TEntity any]( ctx context.Context, listQuery *utils.ListQuery, db *gorm.DB, -) (*utils.ListResult[T], error) { - var items []T - var totalRows int64 - db.Model(items).WithContext(ctx).Count(&totalRows) +) (*utils.ListResult[TEntity], error) { + var ( + items []TEntity + totalRows int64 + ) + + dataModel := typeMapper.GenericInstanceByT[TDataModel]() + // https://gorm.io/docs/advanced_query.html + db.WithContext(ctx).Model(dataModel).Count(&totalRows) // generate where query query := db.WithContext(ctx). + Model(dataModel). Offset(listQuery.GetOffset()). Limit(listQuery.GetLimit()). Order(listQuery.GetOrderBy()) @@ -37,25 +44,27 @@ func Paginate[T any]( switch action { case "equals": whereQuery := fmt.Sprintf("%s = ?", column) - query = query.WithContext(ctx).Where(whereQuery, value) - break + query = query.Where(whereQuery, value) case "contains": whereQuery := fmt.Sprintf("%s LIKE ?", column) - query = query.WithContext(ctx).Where(whereQuery, "%"+value+"%") - break + query = query.Where(whereQuery, "%"+value+"%") case "in": whereQuery := fmt.Sprintf("%s IN (?)", column) queryArray := strings.Split(value, ",") - query = query.WithContext(ctx).Where(whereQuery, queryArray) - break - + query = query.Where(whereQuery, queryArray) } } } + // https://gorm.io/docs/advanced_query.html#Smart-Select-Fields if err := query.Find(&items).Error; err != nil { return nil, errors.WrapIf(err, "error in finding products.") } - return utils.NewListResult[T](items, listQuery.GetSize(), listQuery.GetPage(), totalRows), nil + return utils.NewListResult[TEntity]( + items, + listQuery.GetSize(), + listQuery.GetPage(), + totalRows, + ), nil } diff --git a/internal/pkg/postgresGorm/helpers/helpers.go b/internal/pkg/postgresGorm/helpers/helpers.go new file mode 100644 index 00000000..1c487318 --- /dev/null +++ b/internal/pkg/postgresGorm/helpers/helpers.go @@ -0,0 +1,32 @@ +package helpers + +import ( + "context" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/constants" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/contracts" + + "emperror.dev/errors" + "gorm.io/gorm" +) + +func GetTxFromContext(ctx context.Context) (*gorm.DB, error) { + gCtx, gCtxOk := ctx.(*contracts.GormContext) + if gCtxOk { + return gCtx.Tx, nil + } + + tx, ok := ctx.Value(constants.TxKey).(*gorm.DB) + if !ok { + return nil, errors.New("Transaction not found in context") + } + + return tx, nil +} + +func SetTxToContext(ctx context.Context, tx *gorm.DB) *contracts.GormContext { + ctx = context.WithValue(ctx, constants.TxKey, tx) + gormContext := &contracts.GormContext{Tx: tx, Context: ctx} + + return gormContext +} diff --git a/internal/pkg/postgresGorm/mediatr/pipelines/mediator_transaction_pipeline.go b/internal/pkg/postgresGorm/mediatr/pipelines/mediator_transaction_pipeline.go new file mode 100644 index 00000000..fac0224a --- /dev/null +++ b/internal/pkg/postgresGorm/mediatr/pipelines/mediator_transaction_pipeline.go @@ -0,0 +1,94 @@ +package postgrespipelines + +import ( + "context" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/helpers" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" + + "github.com/mehdihadeli/go-mediatr" + "gorm.io/gorm" +) + +type mediatorTransactionPipeline struct { + logger logger.Logger + db *gorm.DB +} + +func NewMediatorTransactionPipeline( + l logger.Logger, + db *gorm.DB, +) mediatr.PipelineBehavior { + return &mediatorTransactionPipeline{ + logger: l, + db: db, + } +} + +func (m *mediatorTransactionPipeline) Handle( + ctx context.Context, + request interface{}, + next mediatr.RequestHandlerFunc, +) (interface{}, error) { + requestName := typeMapper.GetSnakeTypeName(request) + + txRequest, ok := request.(cqrs.ITxRequest) + if !ok || !txRequest.IsTxRequest() { + return next(ctx) + } + + var result interface{} + + // https://gorm.io/docs/transactions.html#Transaction + tx := m.db.WithContext(ctx).Begin() + + m.logger.Infof( + "beginning database transaction for request `%s`", + requestName, + ) + + gormContext := helpers.SetTxToContext(ctx, tx) + ctx = gormContext + + defer func() { + if r := recover(); r != nil { + tx.WithContext(ctx).Rollback() + + if err, _ := r.(error); err != nil { + m.logger.Errorf( + "panic tn the transaction, rolling back transaction with panic err: %+v", + err, + ) + } else { + m.logger.Errorf("panic tn the transaction, rolling back transaction with panic message: %+v", r) + } + } + }() + + middlewareResponse, err := next(ctx) + result = middlewareResponse + + if err != nil { + m.logger.Errorf( + "rolling back transaction for request `%s`", + requestName, + ) + tx.WithContext(ctx).Rollback() + + return nil, err + } + + m.logger.Infof("committing transaction for request `%s`", requestName) + + if err = tx.WithContext(ctx).Commit().Error; err != nil { + m.logger.Errorf("transaction commit error: ", err) + } + + if err != nil { + return nil, err + } + + return result, nil +} diff --git a/internal/pkg/gorm_postgres/repository/gorm_generic_repository.go b/internal/pkg/postgresGorm/repository/gorm_generic_repository.go similarity index 69% rename from internal/pkg/gorm_postgres/repository/gorm_generic_repository.go rename to internal/pkg/postgresGorm/repository/gorm_generic_repository.go index f0809770..b5a1cbe0 100644 --- a/internal/pkg/gorm_postgres/repository/gorm_generic_repository.go +++ b/internal/pkg/postgresGorm/repository/gorm_generic_repository.go @@ -4,14 +4,15 @@ import ( "context" "fmt" "reflect" + "strings" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/data" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/data/specification" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - reflectionHelper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/reflection_helper" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + reflectionHelper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/reflectionhelper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "emperror.dev/errors" @@ -35,13 +36,18 @@ func NewGenericGormRepositoryWithDataModel[TDataModel interface{}, TEntity inter } // NewGenericGormRepository create new gorm generic repository -func NewGenericGormRepository[TEntity interface{}](db *gorm.DB) data.GenericRepository[TEntity] { +func NewGenericGormRepository[TEntity interface{}]( + db *gorm.DB, +) data.GenericRepository[TEntity] { return &gormGenericRepository[TEntity, TEntity]{ db: db, } } -func (r *gormGenericRepository[TDataModel, TEntity]) Add(ctx context.Context, entity TEntity) error { +func (r *gormGenericRepository[TDataModel, TEntity]) Add( + ctx context.Context, + entity TEntity, +) error { dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() modelType := typeMapper.GetTypeFromGeneric[TEntity]() @@ -50,6 +56,7 @@ func (r *gormGenericRepository[TDataModel, TEntity]) Add(ctx context.Context, en if err != nil { return err } + return nil } else { dataModel, err := mapper.Map[TDataModel](entity) @@ -66,10 +73,14 @@ func (r *gormGenericRepository[TDataModel, TEntity]) Add(ctx context.Context, en } reflectionHelper.SetValue[TEntity](entity, e) } + return nil } -func (r *gormGenericRepository[TDataModel, TEntity]) AddAll(ctx context.Context, entities []TEntity) error { +func (r *gormGenericRepository[TDataModel, TEntity]) AddAll( + ctx context.Context, + entities []TEntity, +) error { for _, entity := range entities { err := r.Add(ctx, entity) if err != nil { @@ -80,23 +91,35 @@ func (r *gormGenericRepository[TDataModel, TEntity]) AddAll(ctx context.Context, return nil } -func (r *gormGenericRepository[TDataModel, TEntity]) GetById(ctx context.Context, id uuid.UUID) (TEntity, error) { +func (r *gormGenericRepository[TDataModel, TEntity]) GetById( + ctx context.Context, + id uuid.UUID, +) (TEntity, error) { dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() modelType := typeMapper.GetTypeFromGeneric[TEntity]() + if modelType == dataModelType { var model TEntity if err := r.db.WithContext(ctx).First(&model, id).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return *new(TEntity), customErrors.NewNotFoundErrorWrap( err, - fmt.Sprintf("can't find the entity with id %s into the database.", id.String()), + fmt.Sprintf( + "can't find the entity with id %s into the database.", + id.String(), + ), ) } + return *new(TEntity), errors.WrapIf( err, - fmt.Sprintf("can't find the entity with id %s into the database.", id.String()), + fmt.Sprintf( + "can't find the entity with id %s into the database.", + id.String(), + ), ) } + return model, nil } else { var dataModel TDataModel @@ -104,12 +127,14 @@ func (r *gormGenericRepository[TDataModel, TEntity]) GetById(ctx context.Context if errors.Is(err, gorm.ErrRecordNotFound) { return *new(TEntity), customErrors.NewNotFoundErrorWrap(err, fmt.Sprintf("can't find the entity with id %s into the database.", id.String())) } + return *new(TEntity), errors.WrapIf(err, fmt.Sprintf("can't find the entity with id %s into the database.", id.String())) } entity, err := mapper.Map[TEntity](dataModel) if err != nil { return *new(TEntity), err } + return entity, nil } } @@ -118,25 +143,16 @@ func (r *gormGenericRepository[TDataModel, TEntity]) GetAll( ctx context.Context, listQuery *utils.ListQuery, ) (*utils.ListResult[TEntity], error) { - dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() - modelType := typeMapper.GetTypeFromGeneric[TEntity]() - if modelType == dataModelType { - result, err := gormPostgres.Paginate[TEntity](ctx, listQuery, r.db) - if err != nil { - return nil, err - } - return result, nil - } else { - result, err := gormPostgres.Paginate[TDataModel](ctx, listQuery, r.db) - if err != nil { - return nil, err - } - models, err := utils.ListResultToListResultDto[TEntity](result) - if err != nil { - return nil, err - } - return models, nil + result, err := gormPostgres.Paginate[TDataModel, TEntity]( + ctx, + listQuery, + r.db, + ) + if err != nil { + return nil, err } + + return result, nil } func (r *gormGenericRepository[TDataModel, TEntity]) Search( @@ -144,48 +160,32 @@ func (r *gormGenericRepository[TDataModel, TEntity]) Search( searchTerm string, listQuery *utils.ListQuery, ) (*utils.ListResult[TEntity], error) { - dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() - modelType := typeMapper.GetTypeFromGeneric[TEntity]() - if modelType == dataModelType { - fields := reflectionHelper.GetAllFields(typeMapper.GetTypeFromGeneric[TEntity]()) - query := r.db + fields := reflectionHelper.GetAllFields( + typeMapper.GetTypeFromGeneric[TDataModel](), + ) + query := r.db - for _, field := range fields { - if field.Type.Kind() != reflect.String { - continue - } - f := strcase.ToSnake(field.Name) - whereQuery := fmt.Sprintf("%s IN (?)", f) - query = r.db.Where(whereQuery, searchTerm) + for _, field := range fields { + if field.Type.Kind() != reflect.String { + continue } - result, err := gormPostgres.Paginate[TEntity](ctx, listQuery, query) - if err != nil { - return nil, err - } - return result, nil - } else { - query := r.db - fields := reflectionHelper.GetAllFields(typeMapper.GetTypeFromGeneric[TDataModel]()) + query = query.Or( + fmt.Sprintf("%s LIKE ?", strcase.ToSnake(field.Name)), + "%"+strings.ToLower(searchTerm)+"%", + ) + } - for _, field := range fields { - if field.Type.Kind() != reflect.String { - continue - } - f := strcase.ToSnake(field.Name) - whereQuery := fmt.Sprintf("%s IN (?)", f) - query = r.db.WithContext(ctx).Where(whereQuery, searchTerm) - } - result, err := gormPostgres.Paginate[TDataModel](ctx, listQuery, query) - if err != nil { - return nil, err - } - models, err := utils.ListResultToListResultDto[TEntity](result) - if err != nil { - return nil, err - } - return models, nil + result, err := gormPostgres.Paginate[TDataModel, TEntity]( + ctx, + listQuery, + query, + ) + if err != nil { + return nil, err } + + return result, nil } func (r *gormGenericRepository[TDataModel, TEntity]) GetByFilter( @@ -229,7 +229,10 @@ func (r *gormGenericRepository[TDataModel, TEntity]) FirstOrDefault( return *new(TEntity), nil } -func (r *gormGenericRepository[TDataModel, TEntity]) Update(ctx context.Context, entity TEntity) error { +func (r *gormGenericRepository[TDataModel, TEntity]) Update( + ctx context.Context, + entity TEntity, +) error { dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() modelType := typeMapper.GetTypeFromGeneric[TEntity]() if modelType == dataModelType { @@ -256,7 +259,10 @@ func (r *gormGenericRepository[TDataModel, TEntity]) Update(ctx context.Context, return nil } -func (r gormGenericRepository[TDataModel, TEntity]) UpdateAll(ctx context.Context, entities []TEntity) error { +func (r *gormGenericRepository[TDataModel, TEntity]) UpdateAll( + ctx context.Context, + entities []TEntity, +) error { for _, e := range entities { err := r.Update(ctx, e) if err != nil { @@ -267,7 +273,10 @@ func (r gormGenericRepository[TDataModel, TEntity]) UpdateAll(ctx context.Contex return nil } -func (r *gormGenericRepository[TDataModel, TEntity]) Delete(ctx context.Context, id uuid.UUID) error { +func (r *gormGenericRepository[TDataModel, TEntity]) Delete( + ctx context.Context, + id uuid.UUID, +) error { entity, err := r.GetById(ctx, id) if err != nil { return err @@ -290,7 +299,11 @@ func (r *gormGenericRepository[TDataModel, TEntity]) SkipTake( modelType := typeMapper.GetTypeFromGeneric[TEntity]() if modelType == dataModelType { var models []TEntity - err := r.db.WithContext(ctx).Offset(skip).Limit(take).Find(&models).Error + err := r.db.WithContext(ctx). + Offset(skip). + Limit(take). + Find(&models). + Error if err != nil { return nil, err } @@ -309,7 +322,9 @@ func (r *gormGenericRepository[TDataModel, TEntity]) SkipTake( } } -func (r *gormGenericRepository[TDataModel, TEntity]) Count(ctx context.Context) int64 { +func (r *gormGenericRepository[TDataModel, TEntity]) Count( + ctx context.Context, +) int64 { var dataModel TDataModel var count int64 r.db.WithContext(ctx).Model(&dataModel).Count(&count) @@ -324,7 +339,10 @@ func (r *gormGenericRepository[TDataModel, TEntity]) Find( modelType := typeMapper.GetTypeFromGeneric[TEntity]() if modelType == dataModelType { var models []TEntity - err := r.db.WithContext(ctx).Where(specification.GetQuery(), specification.GetValues()...).Find(&models).Error + err := r.db.WithContext(ctx). + Where(specification.GetQuery(), specification.GetValues()...). + Find(&models). + Error if err != nil { return nil, err } diff --git a/internal/pkg/postgresGorm/repository/gorm_generic_repository_test.go b/internal/pkg/postgresGorm/repository/gorm_generic_repository_test.go new file mode 100644 index 00000000..b077348b --- /dev/null +++ b/internal/pkg/postgresGorm/repository/gorm_generic_repository_test.go @@ -0,0 +1,496 @@ +package repository + +import ( + "context" + "log" + "testing" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/data" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + gorm2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/testcontainer/gorm" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" + + "github.com/brianvoe/gofakeit/v6" + uuid "github.com/satori/go.uuid" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" + "gorm.io/gorm" + + _ "github.com/lib/pq" // postgres driver +) + +// Product is a domain_events entity +type Product struct { + ID uuid.UUID + Name string + Weight int + IsAvailable bool +} + +// ProductGorm is DTO used to map Product entity to database +type ProductGorm struct { + ID uuid.UUID `gorm:"primaryKey;column:id"` + Name string `gorm:"column:name"` + Weight int `gorm:"column:weight"` + IsAvailable bool `gorm:"column:is_available"` +} + +func (v *ProductGorm) TableName() string { + return "products_gorm" +} + +type gormGenericRepositoryTest struct { + suite.Suite + DB *gorm.DB + productRepository data.GenericRepository[*ProductGorm] + productRepositoryWithDataModel data.GenericRepositoryWithDataModel[*ProductGorm, *Product] + products []*ProductGorm +} + +func TestGormGenericRepository(t *testing.T) { + suite.Run( + t, + &gormGenericRepositoryTest{}, + ) +} + +func (c *gormGenericRepositoryTest) SetupSuite() { + opts, err := gorm2.NewGormTestContainers(defaultLogger.GetLogger()). + PopulateContainerOptions(context.Background(), c.T()) + c.Require().NoError(err) + + gormDB, err := postgresGorm.NewGorm(opts) + c.Require().NoError(err) + c.DB = gormDB + + err = migrationDatabase(gormDB) + c.Require().NoError(err) + + c.productRepository = NewGenericGormRepository[*ProductGorm](gormDB) + c.productRepositoryWithDataModel = NewGenericGormRepositoryWithDataModel[*ProductGorm, *Product]( + gormDB, + ) + + err = mapper.CreateMap[*ProductGorm, *Product]() + if err != nil { + log.Fatal(err) + } + + err = mapper.CreateMap[*Product, *ProductGorm]() + if err != nil { + log.Fatal(err) + } +} + +func (c *gormGenericRepositoryTest) SetupTest() { + p, err := seedData(context.Background(), c.DB) + c.Require().NoError(err) + c.products = p +} + +func (c *gormGenericRepositoryTest) TearDownTest() { + err := c.cleanupPostgresData() + c.Require().NoError(err) +} + +func (c *gormGenericRepositoryTest) Test_Add() { + ctx := context.Background() + + product := &ProductGorm{ + ID: uuid.NewV4(), + Name: gofakeit.Name(), + Weight: gofakeit.Number(100, 1000), + IsAvailable: true, + } + + err := c.productRepository.Add(ctx, product) + c.Require().NoError(err) + + p, err := c.productRepository.GetById(ctx, product.ID) + if err != nil { + return + } + + c.Assert().NotNil(p) + c.Assert().Equal(product.ID, p.ID) +} + +func (c *gormGenericRepositoryTest) Test_Add_With_Data_Model() { + ctx := context.Background() + + product := &Product{ + ID: uuid.NewV4(), + Name: gofakeit.Name(), + Weight: gofakeit.Number(100, 1000), + IsAvailable: true, + } + + err := c.productRepositoryWithDataModel.Add(ctx, product) + c.Require().NoError(err) + + p, err := c.productRepositoryWithDataModel.GetById(ctx, product.ID) + if err != nil { + return + } + + c.Assert().NotNil(p) + c.Assert().Equal(product.ID, p.ID) +} + +func (c *gormGenericRepositoryTest) Test_Get_By_Id() { + ctx := context.Background() + + all, err := c.productRepository.GetAll(ctx, utils.NewListQuery(10, 1)) + c.Require().NoError(err) + + p := all.Items[0] + + testCases := []struct { + Name string + ProductId uuid.UUID + ExpectResult *ProductGorm + }{ + { + Name: p.Name, + ProductId: p.ID, + ExpectResult: p, + }, + { + Name: "NonExistingProduct", + ProductId: uuid.NewV4(), + ExpectResult: nil, + }, + } + + for _, s := range testCases { + c.T().Run(s.Name, func(t *testing.T) { + t.Parallel() + res, err := c.productRepository.GetById(ctx, s.ProductId) + if s.ExpectResult == nil { + assert.Error(t, err) + assert.True(t, customErrors.IsNotFoundError(err)) + assert.Nil(t, res) + } else { + assert.NoError(t, err) + assert.NotNil(t, res) + assert.Equal(t, p.ID, res.ID) + } + }) + } +} + +func (c *gormGenericRepositoryTest) Test_Get_By_Id_With_Data_Model() { + ctx := context.Background() + + all, err := c.productRepositoryWithDataModel.GetAll( + ctx, + utils.NewListQuery(10, 1), + ) + if err != nil { + return + } + p := all.Items[0] + + testCases := []struct { + Name string + ProductId uuid.UUID + ExpectResult *Product + }{ + { + Name: p.Name, + ProductId: p.ID, + ExpectResult: p, + }, + { + Name: "NonExistingProduct", + ProductId: uuid.NewV4(), + ExpectResult: nil, + }, + } + + for _, s := range testCases { + c.T().Run(s.Name, func(t *testing.T) { + t.Parallel() + res, err := c.productRepositoryWithDataModel.GetById( + ctx, + s.ProductId, + ) + + if s.ExpectResult == nil { + assert.Error(t, err) + assert.True(t, customErrors.IsNotFoundError(err)) + assert.Nil(t, res) + } else { + assert.NoError(t, err) + assert.NotNil(t, res) + assert.Equal(t, p.ID, res.ID) + } + }) + } +} + +func (c *gormGenericRepositoryTest) Test_Get_All() { + ctx := context.Background() + + models, err := c.productRepository.GetAll(ctx, utils.NewListQuery(10, 1)) + c.Require().NoError(err) + + c.Assert().NotEmpty(models.Items) +} + +func (c *gormGenericRepositoryTest) Test_Get_All_With_Data_Model() { + ctx := context.Background() + + models, err := c.productRepositoryWithDataModel.GetAll( + ctx, + utils.NewListQuery(10, 1), + ) + c.Require().NoError(err) + + c.Assert().NotEmpty(models.Items) +} + +func (c *gormGenericRepositoryTest) Test_Search() { + ctx := context.Background() + + models, err := c.productRepository.Search( + ctx, + c.products[0].Name, + utils.NewListQuery(10, 1), + ) + c.Require().NoError(err) + + c.Assert().NotEmpty(models.Items) + c.Assert().Equal(len(models.Items), 1) +} + +func (c *gormGenericRepositoryTest) Test_Search_With_Data_Model() { + ctx := context.Background() + + models, err := c.productRepositoryWithDataModel.Search( + ctx, + c.products[0].Name, + utils.NewListQuery(10, 1), + ) + c.Require().NoError(err) + + c.Assert().NotEmpty(models.Items) + c.Assert().Equal(len(models.Items), 1) +} + +func (c *gormGenericRepositoryTest) Test_Where() { + ctx := context.Background() + + models, err := c.productRepository.GetByFilter( + ctx, + map[string]interface{}{"name": c.products[0].Name}, + ) + c.Require().NoError(err) + + c.Assert().NotEmpty(models) + c.Assert().Equal(len(models), 1) +} + +func (c *gormGenericRepositoryTest) Test_Where_With_Data_Model() { + ctx := context.Background() + + models, err := c.productRepositoryWithDataModel.GetByFilter( + ctx, + map[string]interface{}{"name": c.products[0].Name}, + ) + c.Require().NoError(err) + + c.Assert().NotEmpty(models) + c.Assert().Equal(len(models), 1) +} + +func (c *gormGenericRepositoryTest) Test_Update() { + ctx := context.Background() + + products, err := c.productRepository.GetAll(ctx, utils.NewListQuery(10, 1)) + c.Require().NoError(err) + + product := products.Items[0] + + product.Name = "product2_updated" + err = c.productRepository.Update(ctx, product) + c.Require().NoError(err) + + single, err := c.productRepository.GetById(ctx, product.ID) + c.Require().NoError(err) + + c.Assert().NotNil(single) + c.Assert().Equal("product2_updated", single.Name) +} + +func (c *gormGenericRepositoryTest) Test_Update_With_Data_Model() { + ctx := context.Background() + + products, err := c.productRepositoryWithDataModel.GetAll( + ctx, + utils.NewListQuery(10, 1), + ) + c.Require().NoError(err) + + product := products.Items[0] + + product.Name = "product2_updated" + err = c.productRepositoryWithDataModel.Update(ctx, product) + c.Require().NoError(err) + + single, err := c.productRepositoryWithDataModel.GetById(ctx, product.ID) + c.Require().NoError(err) + + c.Assert().NotNil(single) + c.Assert().Equal("product2_updated", single.Name) +} + +//func Test_Delete(t *testing.T) { +// ctx := context.Background() +// repository, err := setupGenericGormRepository(ctx, t) +// +// products, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) +// if err != nil { +// t.Fatal(err) +// } +// product := products.Items[0] +// +// err = repository.Delete(ctx, product.ID) +// if err != nil { +// return +// } +// +// single, err := repository.GetById(ctx, product.ID) +// assert.Nil(t, single) +//} +// +//func Test_Delete_With_Data_Model(t *testing.T) { +// ctx := context.Background() +// repository, err := setupGenericGormRepositoryWithDataModel(ctx, t) +// +// products, err := repository.GetAll(ctx, utils.NewListQuery(10, 1)) +// if err != nil { +// t.Fatal(err) +// } +// product := products.Items[0] +// +// err = repository.Delete(ctx, product.ID) +// if err != nil { +// return +// } +// +// single, err := repository.GetById(ctx, product.ID) +// assert.Nil(t, single) +//} +// +//func Test_Count(t *testing.T) { +// ctx := context.Background() +// repository, err := setupGenericGormRepository(ctx, t) +// if err != nil { +// t.Fatal(err) +// } +// +// count := repository.Count(ctx) +// +// assert.Equal(t, count, int64(2)) +//} +// +//func Test_Count_With_Data_Model(t *testing.T) { +// ctx := context.Background() +// repository, err := setupGenericGormRepositoryWithDataModel(ctx, t) +// if err != nil { +// t.Fatal(err) +// } +// +// count := repository.Count(ctx) +// +// assert.Equal(t, count, int64(2)) +//} +// +//func Test_Find(t *testing.T) { +// ctx := context.Background() +// repository, err := setupGenericGormRepository(ctx, t) +// if err != nil { +// t.Fatal(err) +// } +// +// entities, err := repository.Find( +// ctx, +// specification.And( +// specification.Equal("is_available", true), +// specification.Equal("name", "seed_product1"), +// ), +// ) +// if err != nil { +// return +// } +// assert.Equal(t, len(entities), 1) +//} +// +//func Test_Find_With_Data_Model(t *testing.T) { +// ctx := context.Background() +// repository, err := setupGenericGormRepositoryWithDataModel(ctx, t) +// if err != nil { +// t.Fatal(err) +// } +// +// entities, err := repository.Find( +// ctx, +// specification.And( +// specification.Equal("is_available", true), +// specification.Equal("name", "seed_product1"), +// ), +// ) +// if err != nil { +// return +// } +// assert.Equal(t, len(entities), 1) +//} + +func (c *gormGenericRepositoryTest) cleanupPostgresData() error { + tables := []string{"products_gorm"} + // Iterate over the tables and delete all records + for _, table := range tables { + err := c.DB.Exec("DELETE FROM " + table).Error + + return err + } + + return nil +} + +func migrationDatabase(db *gorm.DB) error { + err := db.AutoMigrate(ProductGorm{}) + if err != nil { + return err + } + + return nil +} + +func seedData(ctx context.Context, db *gorm.DB) ([]*ProductGorm, error) { + seedProducts := []*ProductGorm{ + { + ID: uuid.NewV4(), + Name: "seed_product1", + Weight: 100, + IsAvailable: true, + }, + { + ID: uuid.NewV4(), + Name: "seed_product2", + Weight: 100, + IsAvailable: true, + }, + } + + err := db.WithContext(ctx).Create(seedProducts).Error + if err != nil { + return nil, err + } + + return seedProducts, nil +} diff --git a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go b/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go new file mode 100644 index 00000000..1b4f37f4 --- /dev/null +++ b/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go @@ -0,0 +1,38 @@ +package messagepersistence + +import ( + "context" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/helpers" + + "gorm.io/gorm" +) + +type PostgresMessagePersistenceDBContextActionFunc func(ctx context.Context, messagePersistenceDBContext *PostgresMessagePersistenceDBContext) error + +type PostgresMessagePersistenceDBContext struct { + *gorm.DB + logger logger.Logger +} + +func NewPostgresMessagePersistenceDBContext( + db *gorm.DB, + log logger.Logger, +) *PostgresMessagePersistenceDBContext { + c := &PostgresMessagePersistenceDBContext{DB: db, logger: log} + + return c +} + +// WithTx creates a transactional DBContext with getting tx-gorm from the ctx +func (c *PostgresMessagePersistenceDBContext) WithTx( + ctx context.Context, +) (*PostgresMessagePersistenceDBContext, error) { + tx, err := helpers.GetTxFromContext(ctx) + if err != nil { + return nil, err + } + + return NewPostgresMessagePersistenceDBContext(tx, c.logger), nil +} diff --git a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository.go b/internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository.go new file mode 100644 index 00000000..4b80314d --- /dev/null +++ b/internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository.go @@ -0,0 +1,87 @@ +package messagepersistence + +import ( + "context" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/persistmessage" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + + "gorm.io/gorm" +) + +type postgresMessagePersistenceRepository struct { + db *gorm.DB + logger logger.Logger +} + +func NewMessagePersistenceRepository( + db *gorm.DB, + l logger.Logger, +) persistmessage.MessagePersistenceRepository { + return &postgresMessagePersistenceRepository{db: db, logger: l} +} + +func (m *postgresMessagePersistenceRepository) Add( + ctx context.Context, + storeMessage *persistmessage.StoreMessage, +) error { + result := m.db.WithContext(ctx).Create(storeMessage) + if result.Error != nil { + return result.Error + } + + return nil +} + +func (m *postgresMessagePersistenceRepository) Update( + ctx context.Context, + storeMessage *persistmessage.StoreMessage, +) error { + // TODO implement me + panic("implement me") +} + +func (m *postgresMessagePersistenceRepository) ChangeState( + ctx context.Context, + messageID string, + status persistmessage.MessageStatus, +) error { + // TODO implement me + panic("implement me") +} + +func (m *postgresMessagePersistenceRepository) GetAll( + ctx context.Context, +) ([]*persistmessage.StoreMessage, error) { + // TODO implement me + panic("implement me") +} + +func (m *postgresMessagePersistenceRepository) GetByFilter( + ctx context.Context, + predicate func(*persistmessage.StoreMessage) bool, +) ([]*persistmessage.StoreMessage, error) { + // TODO implement me + panic("implement me") +} + +func (m *postgresMessagePersistenceRepository) GetById( + ctx context.Context, + id string, +) (*persistmessage.StoreMessage, error) { + // TODO implement me + panic("implement me") +} + +func (m *postgresMessagePersistenceRepository) Remove( + ctx context.Context, + storeMessage *persistmessage.StoreMessage, +) (bool, error) { + // TODO implement me + panic("implement me") +} + +func (m *postgresMessagePersistenceRepository) CleanupMessages() { + // TODO implement me + panic("implement me") +} diff --git a/internal/pkg/postgres_pgx/interface.go b/internal/pkg/postgrespgx/interface.go similarity index 100% rename from internal/pkg/postgres_pgx/interface.go rename to internal/pkg/postgrespgx/interface.go diff --git a/internal/pkg/postgres_pgx/postgres.go b/internal/pkg/postgrespgx/postgres.go similarity index 100% rename from internal/pkg/postgres_pgx/postgres.go rename to internal/pkg/postgrespgx/postgres.go diff --git a/internal/pkg/postgres_pgx/postgres_pgx_fx.go b/internal/pkg/postgrespgx/postgres_pgx_fx.go similarity index 100% rename from internal/pkg/postgres_pgx/postgres_pgx_fx.go rename to internal/pkg/postgrespgx/postgres_pgx_fx.go diff --git a/internal/pkg/postgres_pgx/postgres_pgx_options.go b/internal/pkg/postgrespgx/postgres_pgx_options.go similarity index 95% rename from internal/pkg/postgres_pgx/postgres_pgx_options.go rename to internal/pkg/postgrespgx/postgres_pgx_options.go index 4fa2f0e1..9c19f9f7 100644 --- a/internal/pkg/postgres_pgx/postgres_pgx_options.go +++ b/internal/pkg/postgrespgx/postgres_pgx_options.go @@ -3,7 +3,7 @@ package postgres import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/iancoleman/strcase" ) diff --git a/internal/pkg/postgres_sqlx/postgres.go b/internal/pkg/postgressqlx/postgres.go similarity index 100% rename from internal/pkg/postgres_sqlx/postgres.go rename to internal/pkg/postgressqlx/postgres.go diff --git a/internal/pkg/postgres_sqlx/postgres_sqlx_fx.go b/internal/pkg/postgressqlx/postgres_sqlx_fx.go similarity index 100% rename from internal/pkg/postgres_sqlx/postgres_sqlx_fx.go rename to internal/pkg/postgressqlx/postgres_sqlx_fx.go diff --git a/internal/pkg/postgres_sqlx/postgres_sqlx_options.go b/internal/pkg/postgressqlx/postgres_sqlx_options.go similarity index 95% rename from internal/pkg/postgres_sqlx/postgres_sqlx_options.go rename to internal/pkg/postgressqlx/postgres_sqlx_options.go index 2f81d406..eaf53b12 100644 --- a/internal/pkg/postgres_sqlx/postgres_sqlx_options.go +++ b/internal/pkg/postgressqlx/postgres_sqlx_options.go @@ -3,7 +3,7 @@ package postgressqlx import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/iancoleman/strcase" ) diff --git a/internal/pkg/rabbitmq/bus/rabbitmq-bus.go b/internal/pkg/rabbitmq/bus/rabbitmq-bus.go index 95f7355f..958870ad 100644 --- a/internal/pkg/rabbitmq/bus/rabbitmq-bus.go +++ b/internal/pkg/rabbitmq/bus/rabbitmq-bus.go @@ -6,20 +6,20 @@ import ( "reflect" "sync" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/bus" + consumer2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/producer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/bus" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" consumerConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/consumercontracts" producerConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/producercontracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/rabbitmqErrors" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "emperror.dev/errors" "github.com/samber/lo" @@ -31,7 +31,7 @@ type RabbitmqBus interface { } type rabbitmqBus struct { - messageTypeConsumers map[reflect.Type][]consumer.Consumer + messageTypeConsumers map[reflect.Type][]consumer2.Consumer producer producer.Producer rabbitmqConfiguration *configurations.RabbitMQConfiguration rabbitmqConfigBuilder configurations.RabbitMQConfigurationBuilder @@ -60,7 +60,7 @@ func NewRabbitmqBus( consumerFactory: consumerFactory, producerFactory: producerFactory, rabbitmqConfigBuilder: builder, - messageTypeConsumers: map[reflect.Type][]consumer.Consumer{}, + messageTypeConsumers: map[reflect.Type][]consumer2.Consumer{}, } producersConfigurationMap := make( @@ -136,7 +136,7 @@ func (r *rabbitmqBus) IsProduced(h func(message types.IMessage)) { // ConnectConsumer Add a new consumer to existing message type consumers. if there is no consumer, will create a new consumer for the message type func (r *rabbitmqBus) ConnectConsumer( messageType types.IMessage, - consumer consumer.Consumer, + consumer consumer2.Consumer, ) error { typeName := utils.GetMessageBaseReflectType(messageType) @@ -190,7 +190,7 @@ func (r *rabbitmqBus) ConnectRabbitMQConsumer( // ConnectConsumerHandler Add handler to existing consumer. creates new consumer if not exist func (r *rabbitmqBus) ConnectConsumerHandler( messageType types.IMessage, - consumerHandler consumer.ConsumerHandler, + consumerHandler consumer2.ConsumerHandler, ) error { typeName := utils.GetMessageBaseReflectType(messageType) @@ -203,7 +203,7 @@ func (r *rabbitmqBus) ConnectConsumerHandler( } else { // if there is no consumer for a message type, we should create new one and add handler to the consumer consumerBuilder := consumerConfigurations.NewRabbitMQConsumerConfigurationBuilder(messageType) - consumerBuilder.WithHandlers(func(builder consumer.ConsumerHandlerConfigurationBuilder) { + consumerBuilder.WithHandlers(func(builder consumer2.ConsumerHandlerConfigurationBuilder) { builder.AddHandler(consumerHandler) }) consumerConfig := consumerBuilder.Build() @@ -280,7 +280,7 @@ func (r *rabbitmqBus) Stop() error { for _, c := range consumers { waitGroup.Add(1) - go func(c consumer.Consumer) { + go func(c consumer2.Consumer) { defer waitGroup.Done() err := c.Stop() diff --git a/internal/pkg/rabbitmq/bus/rabbitmq_bus_test.go b/internal/pkg/rabbitmq/bus/rabbitmq_bus_test.go index b65c5fa4..5699d3c6 100644 --- a/internal/pkg/rabbitmq/bus/rabbitmq_bus_test.go +++ b/internal/pkg/rabbitmq/bus/rabbitmq_bus_test.go @@ -5,12 +5,12 @@ import ( "fmt" "testing" + messageConsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + pipeline2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/pipeline" + types3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/json" - defaultLogger2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" - messageConsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/pipeline" - types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + defaultLogger2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" consumerConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" @@ -67,7 +67,7 @@ func Test_AddRabbitMQ(t *testing.T) { NewTestMessageHandler2(), ) }). - WIthPipelines(func(consumerPipelineBuilder pipeline.ConsumerPipelineConfigurationBuilder) { + WIthPipelines(func(consumerPipelineBuilder pipeline2.ConsumerPipelineConfigurationBuilder) { consumerPipelineBuilder.AddPipeline(NewPipeline1()) }) }, @@ -98,7 +98,7 @@ func Test_AddRabbitMQ(t *testing.T) { context.Background(), &ProducerConsumerMessage{ Data: "ssssssssss", - Message: types2.NewMessage(uuid.NewV4().String()), + Message: types3.NewMessage(uuid.NewV4().String()), }, nil, ) @@ -113,14 +113,14 @@ func Test_AddRabbitMQ(t *testing.T) { } type ProducerConsumerMessage struct { - *types2.Message + *types3.Message Data string } func NewProducerConsumerMessage(data string) *ProducerConsumerMessage { return &ProducerConsumerMessage{ Data: data, - Message: types2.NewMessage(uuid.NewV4().String()), + Message: types3.NewMessage(uuid.NewV4().String()), } } @@ -133,7 +133,7 @@ func NewTestMessageHandler() *TestMessageHandler { func (t *TestMessageHandler) Handle( ctx context.Context, - consumeContext types2.MessageConsumeContext, + consumeContext types3.MessageConsumeContext, ) error { message := consumeContext.Message().(*ProducerConsumerMessage) fmt.Println(message) @@ -145,7 +145,7 @@ type TestMessageHandler2 struct{} func (t *TestMessageHandler2) Handle( ctx context.Context, - consumeContext types2.MessageConsumeContext, + consumeContext types3.MessageConsumeContext, ) error { message := consumeContext.Message() fmt.Println(message) @@ -160,14 +160,14 @@ func NewTestMessageHandler2() *TestMessageHandler2 { // /////////////// ConsumerPipeline type Pipeline1 struct{} -func NewPipeline1() pipeline.ConsumerPipeline { +func NewPipeline1() pipeline2.ConsumerPipeline { return &Pipeline1{} } func (p *Pipeline1) Handle( ctx context.Context, - consumerContext types2.MessageConsumeContext, - next pipeline.ConsumerHandlerFunc, + consumerContext types3.MessageConsumeContext, + next pipeline2.ConsumerHandlerFunc, ) error { fmt.Println("PipelineBehaviourTest.Handled") diff --git a/internal/pkg/rabbitmq/config/rabbitmq_options.go b/internal/pkg/rabbitmq/config/rabbitmq_options.go index 15aa7d9d..50c99ba6 100644 --- a/internal/pkg/rabbitmq/config/rabbitmq_options.go +++ b/internal/pkg/rabbitmq/config/rabbitmq_options.go @@ -6,7 +6,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/iancoleman/strcase" ) diff --git a/internal/pkg/rabbitmq/configurations/rabbitmq_configuration_builder.go b/internal/pkg/rabbitmq/configurations/rabbitmq_configuration_builder.go index b60fbf51..974dfb65 100644 --- a/internal/pkg/rabbitmq/configurations/rabbitmq_configuration_builder.go +++ b/internal/pkg/rabbitmq/configurations/rabbitmq_configuration_builder.go @@ -1,7 +1,7 @@ package configurations import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" consumerConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" producerConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/configurations" diff --git a/internal/pkg/rabbitmq/consumer/configurations/consumer_connector.go b/internal/pkg/rabbitmq/consumer/configurations/consumer_connector.go index 23b05c6e..89381a6d 100644 --- a/internal/pkg/rabbitmq/consumer/configurations/consumer_connector.go +++ b/internal/pkg/rabbitmq/consumer/configurations/consumer_connector.go @@ -1,8 +1,8 @@ package configurations import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" ) type RabbitMQConsumerConnector interface { diff --git a/internal/pkg/rabbitmq/consumer/configurations/rabbitmq_consumer_configuration.go b/internal/pkg/rabbitmq/consumer/configurations/rabbitmq_consumer_configuration.go index df8ccdc0..69bdbf6f 100644 --- a/internal/pkg/rabbitmq/consumer/configurations/rabbitmq_consumer_configuration.go +++ b/internal/pkg/rabbitmq/consumer/configurations/rabbitmq_consumer_configuration.go @@ -4,10 +4,10 @@ import ( "fmt" "reflect" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/pipeline" - types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/utils" + consumer2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/pipeline" + types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/options" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" ) @@ -16,8 +16,8 @@ type RabbitMQConsumerConfiguration struct { Name string ConsumerMessageType reflect.Type Pipelines []pipeline.ConsumerPipeline - Handlers []consumer.ConsumerHandler - *consumer.ConsumerOptions + Handlers []consumer2.ConsumerHandler + *consumer2.ConsumerOptions ConcurrencyLimit int // The prefetch count tells the Rabbit connection how many messages to retrieve from the server per request. PrefetchCount int @@ -35,7 +35,7 @@ func NewDefaultRabbitMQConsumerConfiguration( name := fmt.Sprintf("%s_consumer", utils.GetMessageName(messageType)) return &RabbitMQConsumerConfiguration{ - ConsumerOptions: &consumer.ConsumerOptions{ExitOnError: false, ConsumerId: ""}, + ConsumerOptions: &consumer2.ConsumerOptions{ExitOnError: false, ConsumerId: ""}, ConcurrencyLimit: 1, PrefetchCount: 4, // how many messages we can handle at once NoLocal: false, diff --git a/internal/pkg/rabbitmq/consumer/configurations/rabbitmq_consumer_configuration_builder.go b/internal/pkg/rabbitmq/consumer/configurations/rabbitmq_consumer_configuration_builder.go index 1e729899..df111bf0 100644 --- a/internal/pkg/rabbitmq/consumer/configurations/rabbitmq_consumer_configuration_builder.go +++ b/internal/pkg/rabbitmq/consumer/configurations/rabbitmq_consumer_configuration_builder.go @@ -1,9 +1,9 @@ package configurations import ( - messageConsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/pipeline" - types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + messageConsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/pipeline" + types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" ) diff --git a/internal/pkg/rabbitmq/consumer/consumercontracts/consumer_factory.go b/internal/pkg/rabbitmq/consumer/consumercontracts/consumer_factory.go index c3cae785..9eb75290 100644 --- a/internal/pkg/rabbitmq/consumer/consumercontracts/consumer_factory.go +++ b/internal/pkg/rabbitmq/consumer/consumercontracts/consumer_factory.go @@ -1,8 +1,8 @@ package consumercontracts import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - messagingTypes "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + messagingTypes "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" ) diff --git a/internal/pkg/rabbitmq/consumer/factory/consumer_factory.go b/internal/pkg/rabbitmq/consumer/factory/consumer_factory.go index 728876e1..70447c6c 100644 --- a/internal/pkg/rabbitmq/consumer/factory/consumer_factory.go +++ b/internal/pkg/rabbitmq/consumer/factory/consumer_factory.go @@ -1,10 +1,10 @@ package factory import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" rabbitmqconsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer" consumerConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" diff --git a/internal/pkg/rabbitmq/consumer/rabbitmq_consumer.go b/internal/pkg/rabbitmq/consumer/rabbitmq_consumer.go index 916df05b..6ea9a771 100644 --- a/internal/pkg/rabbitmq/consumer/rabbitmq_consumer.go +++ b/internal/pkg/rabbitmq/consumer/rabbitmq_consumer.go @@ -6,14 +6,14 @@ import ( "reflect" "time" + consumer3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + consumer2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/otel/tracing/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/pipeline" + types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - consumeTracing "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/otel/tracing/consumer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/pipeline" - messagingTypes "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/rabbitmqErrors" @@ -42,16 +42,16 @@ var retryOptions = []retry.Option{ type rabbitMQConsumer struct { rabbitmqConsumerOptions *configurations.RabbitMQConsumerConfiguration connection types.IConnection - handlerDefault consumer.ConsumerHandler + handlerDefault consumer3.ConsumerHandler channel *amqp091.Channel deliveryRoutines chan struct{} // chan should init before using channel eventSerializer serializer.EventSerializer logger logger.Logger rabbitmqOptions *config.RabbitmqOptions ErrChan chan error - handlers []consumer.ConsumerHandler + handlers []consumer3.ConsumerHandler pipelines []pipeline.ConsumerPipeline - isConsumedNotifications []func(message messagingTypes.IMessage) + isConsumedNotifications []func(message types2.IMessage) } // NewRabbitMQConsumer create a new generic RabbitMQ consumer @@ -61,8 +61,8 @@ func NewRabbitMQConsumer( consumerConfiguration *configurations.RabbitMQConsumerConfiguration, eventSerializer serializer.EventSerializer, logger logger.Logger, - isConsumedNotifications ...func(message messagingTypes.IMessage), -) (consumer.Consumer, error) { + isConsumedNotifications ...func(message types2.IMessage), +) (consumer3.Consumer, error) { if consumerConfiguration == nil { return nil, errors.New("consumer configuration is required") } @@ -94,7 +94,7 @@ func NewRabbitMQConsumer( return cons, nil } -func (r *rabbitMQConsumer) IsConsumed(h func(message messagingTypes.IMessage)) { +func (r *rabbitMQConsumer) IsConsumed(h func(message types2.IMessage)) { r.isConsumedNotifications = append(r.isConsumedNotifications, h) } @@ -253,7 +253,7 @@ func (r *rabbitMQConsumer) Stop() error { } } -func (r *rabbitMQConsumer) ConnectHandler(handler consumer.ConsumerHandler) { +func (r *rabbitMQConsumer) ConnectHandler(handler consumer3.ConsumerHandler) { r.handlers = append(r.handlers, handler) } @@ -301,7 +301,7 @@ func (r *rabbitMQConsumer) handleReceived( meta = metadata.MapToMetadata(delivery.Headers) } - consumerTraceOption := &consumeTracing.ConsumerTracingOptions{ + consumerTraceOption := &consumer2.ConsumerTracingOptions{ MessagingSystem: "rabbitmq", DestinationKind: "queue", Destination: r.rabbitmqConsumerOptions.QueueOptions.Name, @@ -309,7 +309,7 @@ func (r *rabbitMQConsumer) handleReceived( semconv.MessagingRabbitmqDestinationRoutingKey(delivery.RoutingKey), }, } - ctx, beforeConsumeSpan := consumeTracing.StartConsumerSpan( + ctx, beforeConsumeSpan := consumer2.StartConsumerSpan( ctx, &meta, string(delivery.Body), @@ -319,7 +319,7 @@ func (r *rabbitMQConsumer) handleReceived( consumeContext, err := r.createConsumeContext(delivery) if err != nil { r.logger.Error( - consumeTracing.FinishConsumerSpan(beforeConsumeSpan, err), + consumer2.FinishConsumerSpan(beforeConsumeSpan, err), ) return } @@ -333,11 +333,11 @@ func (r *rabbitMQConsumer) handleReceived( if err := delivery.Ack(false); err != nil { r.logger.Error( "error sending ACK to RabbitMQ consumer: %v", - consumeTracing.FinishConsumerSpan(beforeConsumeSpan, err), + consumer2.FinishConsumerSpan(beforeConsumeSpan, err), ) return } - _ = consumeTracing.FinishConsumerSpan(beforeConsumeSpan, nil) + _ = consumer2.FinishConsumerSpan(beforeConsumeSpan, nil) if len(r.isConsumedNotifications) > 0 { for _, notification := range r.isConsumedNotifications { if notification != nil { @@ -351,11 +351,11 @@ func (r *rabbitMQConsumer) handleReceived( if err := delivery.Nack(false, true); err != nil { r.logger.Error( "error in sending Nack to RabbitMQ consumer: %v", - consumeTracing.FinishConsumerSpan(beforeConsumeSpan, err), + consumer2.FinishConsumerSpan(beforeConsumeSpan, err), ) return } - _ = consumeTracing.FinishConsumerSpan(beforeConsumeSpan, nil) + _ = consumer2.FinishConsumerSpan(beforeConsumeSpan, nil) } } @@ -366,7 +366,7 @@ func (r *rabbitMQConsumer) handle( ctx context.Context, ack func(), nack func(), - messageConsumeContext messagingTypes.MessageConsumeContext, + messageConsumeContext types2.MessageConsumeContext, ) { var err error for _, handler := range r.handlers { @@ -390,8 +390,8 @@ func (r *rabbitMQConsumer) handle( func (r *rabbitMQConsumer) runHandlersWithRetry( ctx context.Context, - handler consumer.ConsumerHandler, - messageConsumeContext messagingTypes.MessageConsumeContext, + handler consumer3.ConsumerHandler, + messageConsumeContext types2.MessageConsumeContext, ) error { err := retry.Do(func() error { var lastHandler pipeline.ConsumerHandlerFunc @@ -399,7 +399,7 @@ func (r *rabbitMQConsumer) runHandlersWithRetry( if r.pipelines != nil && len(r.pipelines) > 0 { reversPipes := r.reversOrder(r.pipelines) lastHandler = func(ctx context.Context) error { - handler := handler.(consumer.ConsumerHandler) + handler := handler.(consumer3.ConsumerHandler) return handler.Handle(ctx, messageConsumeContext) } @@ -409,7 +409,7 @@ func (r *rabbitMQConsumer) runHandlersWithRetry( nexValue := next var handlerFunc pipeline.ConsumerHandlerFunc = func(ctx context.Context) error { - genericContext, ok := messageConsumeContext.(messagingTypes.MessageConsumeContext) + genericContext, ok := messageConsumeContext.(types2.MessageConsumeContext) if ok { return pipeValue.Handle( ctx, @@ -419,7 +419,7 @@ func (r *rabbitMQConsumer) runHandlersWithRetry( } return pipeValue.Handle( ctx, - messageConsumeContext.(messagingTypes.MessageConsumeContext), + messageConsumeContext.(types2.MessageConsumeContext), nexValue, ) } @@ -436,7 +436,7 @@ func (r *rabbitMQConsumer) runHandlersWithRetry( } return nil } else { - err := handler.Handle(ctx, messageConsumeContext.(messagingTypes.MessageConsumeContext)) + err := handler.Handle(ctx, messageConsumeContext.(types2.MessageConsumeContext)) if err != nil { return err } @@ -449,18 +449,18 @@ func (r *rabbitMQConsumer) runHandlersWithRetry( func (r *rabbitMQConsumer) createConsumeContext( delivery amqp091.Delivery, -) (messagingTypes.MessageConsumeContext, error) { +) (types2.MessageConsumeContext, error) { message := r.deserializeData( delivery.ContentType, delivery.Type, delivery.Body, ) if reflect.ValueOf(message).IsZero() || reflect.ValueOf(message).IsNil() { - return *new(messagingTypes.MessageConsumeContext), errors.New( + return *new(types2.MessageConsumeContext), errors.New( "error in deserialization of payload", ) } - m, ok := message.(messagingTypes.IMessage) + m, ok := message.(types2.IMessage) if !ok || m.IsMessage() == false { return nil, errors.New( fmt.Sprintf( @@ -475,8 +475,8 @@ func (r *rabbitMQConsumer) createConsumeContext( meta = metadata.MapToMetadata(delivery.Headers) } - consumeContext := messagingTypes.NewMessageConsumeContext( - message.(messagingTypes.IMessage), + consumeContext := types2.NewMessageConsumeContext( + message.(types2.IMessage), meta, delivery.ContentType, delivery.Type, diff --git a/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go b/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go index 323157d2..cab253b7 100644 --- a/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go +++ b/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go @@ -6,12 +6,12 @@ import ( "testing" "time" + messageConsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/pipeline" + types3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/json" - defaultLogger2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" - messageConsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/pipeline" - types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + defaultLogger2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/bus" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" rabbitmqConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" @@ -116,14 +116,14 @@ func Test_Consumer_With_Fake_Message(t *testing.T) { } type ProducerConsumerMessage struct { - *types2.Message + *types3.Message Data string } func NewProducerConsumerMessage(data string) *ProducerConsumerMessage { return &ProducerConsumerMessage{ Data: data, - Message: types2.NewMessage(uuid.NewV4().String()), + Message: types3.NewMessage(uuid.NewV4().String()), } } @@ -132,7 +132,7 @@ type TestMessageHandler struct{} func (t *TestMessageHandler) Handle( ctx context.Context, - consumeContext types2.MessageConsumeContext, + consumeContext types3.MessageConsumeContext, ) error { message := consumeContext.Message().(*ProducerConsumerMessage) fmt.Println(message) @@ -148,7 +148,7 @@ type TestMessageHandler2 struct{} func (t *TestMessageHandler2) Handle( ctx context.Context, - consumeContext types2.MessageConsumeContext, + consumeContext types3.MessageConsumeContext, ) error { message := consumeContext.Message() fmt.Println(message) @@ -169,7 +169,7 @@ func NewPipeline1() pipeline.ConsumerPipeline { func (p Pipeline1) Handle( ctx context.Context, - consumerContext types2.MessageConsumeContext, + consumerContext types3.MessageConsumeContext, next pipeline.ConsumerHandlerFunc, ) error { fmt.Println("PipelineBehaviourTest.Handled") diff --git a/internal/pkg/rabbitmq/producer/configurations/rabbitmq_producer_configuration.go b/internal/pkg/rabbitmq/producer/configurations/rabbitmq_producer_configuration.go index e30747f1..c0aaef52 100644 --- a/internal/pkg/rabbitmq/producer/configurations/rabbitmq_producer_configuration.go +++ b/internal/pkg/rabbitmq/producer/configurations/rabbitmq_producer_configuration.go @@ -3,8 +3,8 @@ package configurations import ( "reflect" - types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/utils" + types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/options" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" ) diff --git a/internal/pkg/rabbitmq/producer/configurations/rabitmq_producer_configuration_builder.go b/internal/pkg/rabbitmq/producer/configurations/rabitmq_producer_configuration_builder.go index 80145b0c..c14541e4 100644 --- a/internal/pkg/rabbitmq/producer/configurations/rabitmq_producer_configuration_builder.go +++ b/internal/pkg/rabbitmq/producer/configurations/rabitmq_producer_configuration_builder.go @@ -1,7 +1,7 @@ package configurations import ( - types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" ) diff --git a/internal/pkg/rabbitmq/producer/producer_factory.go b/internal/pkg/rabbitmq/producer/producer_factory.go index e2f324ce..d01b9283 100644 --- a/internal/pkg/rabbitmq/producer/producer_factory.go +++ b/internal/pkg/rabbitmq/producer/producer_factory.go @@ -1,10 +1,10 @@ package producer import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/producer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" producerConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/producercontracts" diff --git a/internal/pkg/rabbitmq/producer/producercontracts/producer_factory.go b/internal/pkg/rabbitmq/producer/producercontracts/producer_factory.go index f407b881..f34ee7d2 100644 --- a/internal/pkg/rabbitmq/producer/producercontracts/producer_factory.go +++ b/internal/pkg/rabbitmq/producer/producercontracts/producer_factory.go @@ -1,8 +1,8 @@ package producercontracts import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" - types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/producer" + types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/configurations" ) diff --git a/internal/pkg/rabbitmq/producer/rabbitmq_producer.go b/internal/pkg/rabbitmq/producer/rabbitmq_producer.go index 131a5f1a..380c320a 100644 --- a/internal/pkg/rabbitmq/producer/rabbitmq_producer.go +++ b/internal/pkg/rabbitmq/producer/rabbitmq_producer.go @@ -5,18 +5,18 @@ import ( "fmt" "time" + messageHeader "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/messageheader" + producer3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/otel/tracing/producer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/producer" + types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - messageHeader "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/message_header" - producer2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/otel/tracing/producer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" - types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "emperror.dev/errors" "github.com/rabbitmq/amqp091-go" @@ -116,7 +116,7 @@ func (r *rabbitMQProducer) PublishMessageWithTopicName( meta = r.getMetadata(message, meta) - producerOptions := &producer2.ProducerTracingOptions{ + producerOptions := &producer3.ProducerTracingOptions{ MessagingSystem: "rabbitmq", DestinationKind: "exchange", Destination: exchange, @@ -130,7 +130,7 @@ func (r *rabbitMQProducer) PublishMessageWithTopicName( return err } - ctx, beforeProduceSpan := producer2.StartProducerSpan( + ctx, beforeProduceSpan := producer3.StartProducerSpan( ctx, message, &meta, @@ -140,14 +140,14 @@ func (r *rabbitMQProducer) PublishMessageWithTopicName( // https://github.com/rabbitmq/rabbitmq-tutorials/blob/master/go/publisher_confirms.go if r.connection == nil { - return producer2.FinishProducerSpan( + return producer3.FinishProducerSpan( beforeProduceSpan, errors.New("connection is nil"), ) } if r.connection.IsClosed() { - return producer2.FinishProducerSpan( + return producer3.FinishProducerSpan( beforeProduceSpan, errors.New("connection is closed, wait for connection alive"), ) @@ -156,17 +156,17 @@ func (r *rabbitMQProducer) PublishMessageWithTopicName( // create a unique channel on the connection and in the end close the channel channel, err := r.connection.Channel() if err != nil { - return producer2.FinishProducerSpan(beforeProduceSpan, err) + return producer3.FinishProducerSpan(beforeProduceSpan, err) } defer channel.Close() err = r.ensureExchange(producerConfiguration, channel, exchange) if err != nil { - return producer2.FinishProducerSpan(beforeProduceSpan, err) + return producer3.FinishProducerSpan(beforeProduceSpan, err) } if err := channel.Confirm(false); err != nil { - return producer2.FinishProducerSpan(beforeProduceSpan, err) + return producer3.FinishProducerSpan(beforeProduceSpan, err) } confirms := make(chan amqp091.Confirmation) @@ -197,11 +197,11 @@ func (r *rabbitMQProducer) PublishMessageWithTopicName( props, ) if err != nil { - return producer2.FinishProducerSpan(beforeProduceSpan, err) + return producer3.FinishProducerSpan(beforeProduceSpan, err) } if confirmed := <-confirms; !confirmed.Ack { - return producer2.FinishProducerSpan( + return producer3.FinishProducerSpan( beforeProduceSpan, errors.New("ack not confirmed"), ) @@ -215,7 +215,7 @@ func (r *rabbitMQProducer) PublishMessageWithTopicName( } } - return producer2.FinishProducerSpan(beforeProduceSpan, err) + return producer3.FinishProducerSpan(beforeProduceSpan, err) } func (r *rabbitMQProducer) getMetadata( diff --git a/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go b/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go index 73867303..8920bd34 100644 --- a/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go +++ b/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go @@ -5,10 +5,10 @@ import ( "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" + types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/json" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" - types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" diff --git a/internal/pkg/rabbitmq/rabbitmq_fx.go b/internal/pkg/rabbitmq/rabbitmq_fx.go index c966fc4e..81ffc4ff 100644 --- a/internal/pkg/rabbitmq/rabbitmq_fx.go +++ b/internal/pkg/rabbitmq/rabbitmq_fx.go @@ -5,10 +5,10 @@ import ( "fmt" "time" + bus2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/bus" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/producer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - bus2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/bus" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/bus" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/factory" diff --git a/internal/pkg/rabbitmq/test/in-memory/rabbitmq_harnes.go b/internal/pkg/rabbitmq/test/in-memory/rabbitmq_harnes.go index 58699134..90ebf9b4 100644 --- a/internal/pkg/rabbitmq/test/in-memory/rabbitmq_harnes.go +++ b/internal/pkg/rabbitmq/test/in-memory/rabbitmq_harnes.go @@ -3,15 +3,15 @@ package in_memory import ( "context" + consumer2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" ) type RabbitmqInMemoryHarnesses struct { publishedMessage []types.IMessage consumedMessage []types.IMessage - consumerHandlers map[types.IMessage][]consumer.ConsumerHandler + consumerHandlers map[types.IMessage][]consumer2.ConsumerHandler } func NewRabbitmqInMemoryHarnesses() *RabbitmqInMemoryHarnesses { @@ -53,7 +53,7 @@ func (r *RabbitmqInMemoryHarnesses) Stop(ctx context.Context) error { func (r *RabbitmqInMemoryHarnesses) ConnectConsumerHandler( messageType types.IMessage, - consumerHandler consumer.ConsumerHandler, + consumerHandler consumer2.ConsumerHandler, ) error { r.consumerHandlers[messageType] = append(r.consumerHandlers[messageType], consumerHandler) return nil @@ -61,7 +61,7 @@ func (r *RabbitmqInMemoryHarnesses) ConnectConsumerHandler( func (r *RabbitmqInMemoryHarnesses) ConnectConsumer( messageType types.IMessage, - consumer consumer.Consumer, + consumer consumer2.Consumer, ) error { return nil } diff --git a/internal/pkg/rabbitmq/types/connection.go b/internal/pkg/rabbitmq/types/connection.go index 5f77d835..f7e3a645 100644 --- a/internal/pkg/rabbitmq/types/connection.go +++ b/internal/pkg/rabbitmq/types/connection.go @@ -3,7 +3,7 @@ package types import ( "fmt" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" diff --git a/internal/pkg/redis/redis_options.go b/internal/pkg/redis/redis_options.go index 7cb2ee3c..3e35fe2e 100644 --- a/internal/pkg/redis/redis_options.go +++ b/internal/pkg/redis/redis_options.go @@ -3,7 +3,7 @@ package redis import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/iancoleman/strcase" ) diff --git a/internal/pkg/reflection/reflection_helper/reflection_helper.go b/internal/pkg/reflection/reflectionhelper/reflection_helper.go similarity index 100% rename from internal/pkg/reflection/reflection_helper/reflection_helper.go rename to internal/pkg/reflection/reflectionhelper/reflection_helper.go diff --git a/internal/pkg/reflection/reflection_helper/reflection_helper_test.go b/internal/pkg/reflection/reflectionhelper/reflection_helper_test.go similarity index 100% rename from internal/pkg/reflection/reflection_helper/reflection_helper_test.go rename to internal/pkg/reflection/reflectionhelper/reflection_helper_test.go diff --git a/internal/pkg/reflection/type_mappper/type_mapper.go b/internal/pkg/reflection/typemapper/type_mapper.go similarity index 97% rename from internal/pkg/reflection/type_mappper/type_mapper.go rename to internal/pkg/reflection/typemapper/type_mapper.go index 713986b6..3e9ee222 100644 --- a/internal/pkg/reflection/type_mappper/type_mapper.go +++ b/internal/pkg/reflection/typemapper/type_mapper.go @@ -157,6 +157,10 @@ func TypesImplementedInterface[TInterface interface{}]() []reflect.Type { // GetFullTypeName returns the full name of the type by its package name func GetFullTypeName(input interface{}) string { + if input == nil { + return "" + } + t := reflect.TypeOf(input) return t.String() } @@ -167,6 +171,10 @@ func GetFullTypeNameByType(typ reflect.Type) string { // GetTypeName returns the name of the type without its package name func GetTypeName(input interface{}) string { + if input == nil { + return "" + } + t := reflect.TypeOf(input) if t.Kind() != reflect.Ptr { return t.Name() @@ -177,6 +185,10 @@ func GetTypeName(input interface{}) string { // GetNonePointerTypeName returns the name of the type without its package name and its pointer func GetNonePointerTypeName(input interface{}) string { + if input == nil { + return "" + } + t := reflect.TypeOf(input) if t.Kind() != reflect.Ptr { return t.Name() @@ -186,6 +198,10 @@ func GetNonePointerTypeName(input interface{}) string { } func GetSnakeTypeName(input interface{}) string { + if input == nil { + return "" + } + t := reflect.TypeOf(input) if t.Kind() != reflect.Ptr { return t.Name() @@ -204,6 +220,10 @@ func GetTypeNameByT[T any]() string { } func GetNonPointerTypeName(input interface{}) string { + if input == nil { + return "" + } + t := reflect.TypeOf(input) if t.Kind() != reflect.Ptr { return t.Name() @@ -213,6 +233,10 @@ func GetNonPointerTypeName(input interface{}) string { } func GetTypeNameByType(typ reflect.Type) string { + if typ == nil { + return "" + } + if typ.Kind() != reflect.Ptr { return typ.Name() } diff --git a/internal/pkg/reflection/type_mappper/type_mapper_test.go b/internal/pkg/reflection/typemapper/type_mapper_test.go similarity index 100% rename from internal/pkg/reflection/type_mappper/type_mapper_test.go rename to internal/pkg/reflection/typemapper/type_mapper_test.go diff --git a/internal/pkg/reflection/type_mappper/unsafe_types.go b/internal/pkg/reflection/typemapper/unsafe_types.go similarity index 100% rename from internal/pkg/reflection/type_mappper/unsafe_types.go rename to internal/pkg/reflection/typemapper/unsafe_types.go diff --git a/internal/pkg/reflection/type_registry/type_registry.go b/internal/pkg/reflection/typeregistry/type_registry.go similarity index 95% rename from internal/pkg/reflection/type_registry/type_registry.go rename to internal/pkg/reflection/typeregistry/type_registry.go index d981fa33..1cef8174 100644 --- a/internal/pkg/reflection/type_registry/type_registry.go +++ b/internal/pkg/reflection/typeregistry/type_registry.go @@ -1,4 +1,4 @@ -package type_registry +package typeregistry // Ref:https://stackoverflow.com/questions/23030884/is-there-a-way-to-create-an-instance-of-a-struct-from-a-string import "reflect" diff --git a/internal/pkg/test/containers/contracts/gorm_container.go b/internal/pkg/test/containers/contracts/gorm_container.go index 18f14664..93147041 100644 --- a/internal/pkg/test/containers/contracts/gorm_container.go +++ b/internal/pkg/test/containers/contracts/gorm_container.go @@ -4,7 +4,7 @@ import ( "context" "testing" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" ) type PostgresContainerOptions struct { diff --git a/internal/pkg/test/containers/contracts/postgrespgx_container.go b/internal/pkg/test/containers/contracts/postgrespgx_container.go index b7267258..3c11f535 100644 --- a/internal/pkg/test/containers/contracts/postgrespgx_container.go +++ b/internal/pkg/test/containers/contracts/postgrespgx_container.go @@ -4,7 +4,7 @@ import ( "context" "testing" - postgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgres_pgx" + postgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgrespgx" ) type PostgresPgxContainer interface { diff --git a/internal/pkg/test/containers/dockertest/gorm/gorm_container.go b/internal/pkg/test/containers/dockertest/gorm/gorm_container.go index 15584d43..0dcf7696 100644 --- a/internal/pkg/test/containers/dockertest/gorm/gorm_container.go +++ b/internal/pkg/test/containers/dockertest/gorm/gorm_container.go @@ -6,7 +6,7 @@ import ( "strconv" "testing" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/contracts" "github.com/ory/dockertest/v3" diff --git a/internal/pkg/test/containers/dockertest/gorm/gorm_container_test.go b/internal/pkg/test/containers/dockertest/gorm/gorm_container_test.go index 8e5ce2dd..e6aeeb53 100644 --- a/internal/pkg/test/containers/dockertest/gorm/gorm_container_test.go +++ b/internal/pkg/test/containers/dockertest/gorm/gorm_container_test.go @@ -7,9 +7,9 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" "github.com/stretchr/testify/assert" "go.uber.org/fx" diff --git a/internal/pkg/test/containers/dockertest/gorm/gorm_fx.go b/internal/pkg/test/containers/dockertest/gorm/gorm_fx.go index 0e888dfd..6901f5b4 100644 --- a/internal/pkg/test/containers/dockertest/gorm/gorm_fx.go +++ b/internal/pkg/test/containers/dockertest/gorm/gorm_fx.go @@ -4,7 +4,7 @@ import ( "context" "testing" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" ) var GormDockerTestConatnerOptionsDecorator = func(t *testing.T, ctx context.Context) interface{} { diff --git a/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_container_test.go b/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_container_test.go index 414b51cd..f4b79837 100644 --- a/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_container_test.go +++ b/internal/pkg/test/containers/dockertest/rabbitmq/rabbitmq_container_test.go @@ -8,12 +8,12 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/bus" + messageConsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/bus" - messageConsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" rabbitmq2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" rabbitmqConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" diff --git a/internal/pkg/test/containers/gnomock/gorm/gorm_container.go b/internal/pkg/test/containers/gnomock/gorm/gorm_container.go index 2c504f67..fb469815 100644 --- a/internal/pkg/test/containers/gnomock/gorm/gorm_container.go +++ b/internal/pkg/test/containers/gnomock/gorm/gorm_container.go @@ -5,7 +5,7 @@ import ( "log" "testing" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/contracts" "emperror.dev/errors" diff --git a/internal/pkg/test/containers/testcontainer/gorm/gorm_container.go b/internal/pkg/test/containers/testcontainer/gorm/gorm_container.go index 36e21092..2cacd21c 100644 --- a/internal/pkg/test/containers/testcontainer/gorm/gorm_container.go +++ b/internal/pkg/test/containers/testcontainer/gorm/gorm_container.go @@ -6,8 +6,8 @@ import ( "testing" "time" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/contracts" "emperror.dev/errors" diff --git a/internal/pkg/test/containers/testcontainer/gorm/gorm_container_test.go b/internal/pkg/test/containers/testcontainer/gorm/gorm_container_test.go index 0e58867e..17ef7d98 100644 --- a/internal/pkg/test/containers/testcontainer/gorm/gorm_container_test.go +++ b/internal/pkg/test/containers/testcontainer/gorm/gorm_container_test.go @@ -8,9 +8,9 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" "github.com/docker/go-connections/nat" "github.com/stretchr/testify/assert" diff --git a/internal/pkg/test/containers/testcontainer/gorm/gorm_fx.go b/internal/pkg/test/containers/testcontainer/gorm/gorm_fx.go index 5b752225..669e1ec7 100644 --- a/internal/pkg/test/containers/testcontainer/gorm/gorm_fx.go +++ b/internal/pkg/test/containers/testcontainer/gorm/gorm_fx.go @@ -4,8 +4,8 @@ import ( "context" "testing" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" ) var GormContainerOptionsDecorator = func(t *testing.T, ctx context.Context) interface{} { diff --git a/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_container.go b/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_container.go index a051afba..97c9848e 100644 --- a/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_container.go +++ b/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_container.go @@ -7,7 +7,7 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - postgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgres_pgx" + postgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgrespgx" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/contracts" "emperror.dev/errors" diff --git a/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_container_test.go b/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_container_test.go index 2488b5e7..9e746273 100644 --- a/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_container_test.go +++ b/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_container_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_fx.go b/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_fx.go index 889e1f4e..161288af 100644 --- a/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_fx.go +++ b/internal/pkg/test/containers/testcontainer/postgrespxg/postgrespgx_fx.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - postgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgres_pgx" + postgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgrespgx" ) var PostgresPgxContainerOptionsDecorator = func(t *testing.T, ctx context.Context) interface{} { diff --git a/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_container_test.go b/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_container_test.go index 910c366d..8d9b1970 100644 --- a/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_container_test.go +++ b/internal/pkg/test/containers/testcontainer/rabbitmq/rabbitmq_container_test.go @@ -8,12 +8,12 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/bus" + messageConsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/bus" - messageConsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" rabbitmq2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" rabbitmqConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" diff --git a/internal/pkg/test/messaging/consumer/rabbitmq_fake_consumer.go b/internal/pkg/test/messaging/consumer/rabbitmq_fake_consumer.go index a32ee866..e0919e7e 100644 --- a/internal/pkg/test/messaging/consumer/rabbitmq_fake_consumer.go +++ b/internal/pkg/test/messaging/consumer/rabbitmq_fake_consumer.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/hypothesis" ) diff --git a/internal/pkg/test/messaging/utils.go b/internal/pkg/test/messaging/utils.go index 270956cd..14788cc7 100644 --- a/internal/pkg/test/messaging/utils.go +++ b/internal/pkg/test/messaging/utils.go @@ -3,10 +3,10 @@ package messaging import ( "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/bus" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/utils" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/bus" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/utils" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/hypothesis" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging/consumer" ) diff --git a/internal/pkg/utils/error_utils/errors.go b/internal/pkg/utils/error_utils/errors.go index 48337c6b..308ef2e0 100644 --- a/internal/pkg/utils/error_utils/errors.go +++ b/internal/pkg/utils/error_utils/errors.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/contracts" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "emperror.dev/errors" ) diff --git a/internal/services/catalog_read_service/internal/products/configurations/rabbitmq/rabbitmq_configuration.go b/internal/services/catalog_read_service/internal/products/configurations/rabbitmq/rabbitmq_configuration.go index 1d7a1de9..b63b44db 100644 --- a/internal/services/catalog_read_service/internal/products/configurations/rabbitmq/rabbitmq_configuration.go +++ b/internal/services/catalog_read_service/internal/products/configurations/rabbitmq/rabbitmq_configuration.go @@ -1,8 +1,8 @@ package rabbitmq import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" rabbitmqConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" diff --git a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created.go b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created.go index 5333c384..03519291 100644 --- a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created.go +++ b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created.go @@ -3,7 +3,7 @@ package externalEvents import ( "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" ) type ProductCreatedV1 struct { diff --git a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created_consumer.go b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created_consumer.go index dc9030f6..c47b9738 100644 --- a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created_consumer.go +++ b/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created_consumer.go @@ -4,10 +4,10 @@ import ( "context" "fmt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/dtos" diff --git a/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted.go b/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted.go index a93dfa62..17f790ec 100644 --- a/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted.go +++ b/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted.go @@ -1,7 +1,7 @@ package externalEvents import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" ) type ProductDeletedV1 struct { diff --git a/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted_consumer.go b/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted_consumer.go index 829d8baa..7b91c075 100644 --- a/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted_consumer.go +++ b/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted_consumer.go @@ -3,10 +3,10 @@ package externalEvents import ( "context" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/deleting_products/v1/commands" diff --git a/internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated.go b/internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated.go index 289e1342..27cf00e7 100644 --- a/internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated.go +++ b/internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated.go @@ -3,7 +3,7 @@ package externalEvents import ( "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" ) type ProductUpdatedV1 struct { diff --git a/internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated_consumer.go b/internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated_consumer.go index 2837cd73..1defa8a6 100644 --- a/internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated_consumer.go +++ b/internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated_consumer.go @@ -4,10 +4,10 @@ import ( "context" "fmt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/consumer" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" diff --git a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go b/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go index 35130df2..38925055 100644 --- a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go +++ b/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go @@ -3,13 +3,15 @@ package infrastructure import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/pipelines" + loggingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/pipelines" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" - pipelines2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/mediatr/pipelines" + metricspipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/mediatr/pipelines" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" tracingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/mediatr/pipelines" + postgrespipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/mediatr/pipelines" "github.com/mehdihadeli/go-mediatr" + "gorm.io/gorm" ) type InfrastructureConfigurator struct { @@ -26,17 +28,18 @@ func NewInfrastructureConfigurator( func (ic *InfrastructureConfigurator) ConfigInfrastructures() { ic.ResolveFunc( - func(logger logger.Logger, tracer tracing.AppTracer, metrics metrics.AppMetrics) error { + func(l logger.Logger, tracer tracing.AppTracer, metrics metrics.AppMetrics, db *gorm.DB) error { err := mediatr.RegisterRequestPipelineBehaviors( - pipelines.NewLoggingPipeline(logger), + loggingpipelines.NewMediatorLoggingPipeline(l), tracingpipelines.NewMediatorTracingPipeline( tracer, - tracingpipelines.WithLogger(logger), + tracingpipelines.WithLogger(l), ), - pipelines2.NewMediatorMetricsPipeline( + metricspipelines.NewMediatorMetricsPipeline( metrics, - pipelines2.WithLogger(logger), + metricspipelines.WithLogger(l), ), + postgrespipelines.NewMediatorTransactionPipeline(l, db), ) return err diff --git a/internal/services/catalog_read_service/internal/shared/test_fixture/integration/integration_test_fixture.go b/internal/services/catalog_read_service/internal/shared/testfixture/integration/integration_test_fixture.go similarity index 96% rename from internal/services/catalog_read_service/internal/shared/test_fixture/integration/integration_test_fixture.go rename to internal/services/catalog_read_service/internal/shared/testfixture/integration/integration_test_fixture.go index 2dbb824a..d485a7d4 100644 --- a/internal/services/catalog_read_service/internal/shared/test_fixture/integration/integration_test_fixture.go +++ b/internal/services/catalog_read_service/internal/shared/testfixture/integration/integration_test_fixture.go @@ -5,9 +5,9 @@ import ( "testing" "time" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/bus" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/bus" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" config2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" @@ -73,8 +73,8 @@ func NewIntegrationTestSharedFixture( return shared } -func (i *IntegrationTestSharedFixture) InitializeTest() { - i.Log.Info("InitializeTest started") +func (i *IntegrationTestSharedFixture) SetupTest() { + i.Log.Info("SetupTest started") // seed data in each test res, err := seedData(i.mongoClient, i.MongoOptions.Database) @@ -85,8 +85,8 @@ func (i *IntegrationTestSharedFixture) InitializeTest() { i.Items = res } -func (i *IntegrationTestSharedFixture) DisposeTest() { - i.Log.Info("DisposeTest started") +func (i *IntegrationTestSharedFixture) TearDownTest() { + i.Log.Info("TearDownTest started") // cleanup test containers with their hooks if err := i.cleanupRabbitmqData(); err != nil { diff --git a/internal/services/catalog_read_service/test/end_to_end/products/features/getting_product_by_id/v1/get_product_by_id_test.go b/internal/services/catalog_read_service/test/end_to_end/products/features/getting_product_by_id/v1/get_product_by_id_test.go index 19746ca7..d37b30e9 100644 --- a/internal/services/catalog_read_service/test/end_to_end/products/features/getting_product_by_id/v1/get_product_by_id_test.go +++ b/internal/services/catalog_read_service/test/end_to_end/products/features/getting_product_by_id/v1/get_product_by_id_test.go @@ -8,7 +8,7 @@ import ( "net/http" "testing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/test_fixture/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/testfixture/integration" "github.com/gavv/httpexpect/v2" @@ -19,7 +19,7 @@ func TestGetProductById(t *testing.T) { e2eFixture := integration.NewIntegrationTestSharedFixture(t) Convey("Get Product By Id Feature", t, func() { - e2eFixture.InitializeTest() + e2eFixture.SetupTest() ctx := context.Background() id := e2eFixture.Items[0].Id @@ -39,6 +39,6 @@ func TestGetProductById(t *testing.T) { }) }) - e2eFixture.DisposeTest() + e2eFixture.TearDownTest() }) } diff --git a/internal/services/catalog_read_service/test/end_to_end/products/features/getting_products/v1/get_products_endpoint_test.go b/internal/services/catalog_read_service/test/end_to_end/products/features/getting_products/v1/get_products_endpoint_test.go index 124c17e9..8c7833c5 100644 --- a/internal/services/catalog_read_service/test/end_to_end/products/features/getting_products/v1/get_products_endpoint_test.go +++ b/internal/services/catalog_read_service/test/end_to_end/products/features/getting_products/v1/get_products_endpoint_test.go @@ -8,7 +8,7 @@ import ( "net/http" "testing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/test_fixture/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/testfixture/integration" "github.com/gavv/httpexpect/v2" @@ -19,7 +19,7 @@ func TestGetAllProducts(t *testing.T) { e2eFixture := integration.NewIntegrationTestSharedFixture(t) Convey("Get All Products Feature", t, func() { - e2eFixture.InitializeTest() + e2eFixture.SetupTest() ctx := context.Background() Convey("Get all products returns ok status", func() { @@ -35,6 +35,6 @@ func TestGetAllProducts(t *testing.T) { }) }) - e2eFixture.DisposeTest() + e2eFixture.TearDownTest() }) } diff --git a/internal/services/catalog_read_service/test/integration/products/data/mongo_product_repository_test.go b/internal/services/catalog_read_service/test/integration/products/data/mongo_product_repository_test.go index 7349a946..4ec46057 100644 --- a/internal/services/catalog_read_service/test/integration/products/data/mongo_product_repository_test.go +++ b/internal/services/catalog_read_service/test/integration/products/data/mongo_product_repository_test.go @@ -11,7 +11,7 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/models" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/test_fixture/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/testfixture/integration" "github.com/brianvoe/gofakeit/v6" uuid "github.com/satori/go.uuid" @@ -24,7 +24,7 @@ func TestProductPostgresRepository(t *testing.T) { // scenario Convey("Product Repository", t, func() { - integrationTestSharedFixture.InitializeTest() + integrationTestSharedFixture.SetupTest() Convey("When we create the new product in the database", func() { ctx := context.Background() @@ -165,6 +165,6 @@ func TestProductPostgresRepository(t *testing.T) { }) }) - integrationTestSharedFixture.DisposeTest() + integrationTestSharedFixture.TearDownTest() }) } diff --git a/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/commands/create_product_test.go b/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/commands/create_product_test.go index 5486a625..cc66cb18 100644 --- a/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/commands/create_product_test.go +++ b/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/commands/create_product_test.go @@ -10,7 +10,7 @@ import ( v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/dtos" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/test_fixture/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/testfixture/integration" "github.com/brianvoe/gofakeit/v6" "github.com/mehdihadeli/go-mediatr" @@ -24,7 +24,7 @@ func TestCreateProduct(t *testing.T) { Convey("Creating Product Feature", t, func() { ctx := context.Background() - integrationTestSharedFixture.InitializeTest() + integrationTestSharedFixture.SetupTest() // https://specflow.org/learn/gherkin/#learn-gherkin // scenario @@ -78,6 +78,6 @@ func TestCreateProduct(t *testing.T) { }, ) - integrationTestSharedFixture.DisposeTest() + integrationTestSharedFixture.TearDownTest() }) } diff --git a/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/events/product_created_test.go b/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/events/product_created_test.go index c6acd362..752f13c9 100644 --- a/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/events/product_created_test.go +++ b/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/events/product_created_test.go @@ -10,12 +10,12 @@ import ( "testing" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging" testUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/utils" externalEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1/events/integrationevents/externalevents" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/models" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/test_fixture/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/testfixture/integration" "github.com/brianvoe/gofakeit/v6" uuid "github.com/satori/go.uuid" @@ -33,7 +33,7 @@ func TestProductCreatedConsumer(t *testing.T) { Convey("Product Created Feature", t, func() { // will execute with each subtest - integrationTestSharedFixture.InitializeTest() + integrationTestSharedFixture.SetupTest() ctx := context.Background() // https://specflow.org/learn/gherkin/#learn-gherkin @@ -107,7 +107,7 @@ func TestProductCreatedConsumer(t *testing.T) { }) }) - integrationTestSharedFixture.DisposeTest() + integrationTestSharedFixture.TearDownTest() }) integrationTestSharedFixture.Log.Info("TearDownSuite started") diff --git a/internal/services/catalog_read_service/test/integration/products/features/deleting_product/v1/commands/delete_product_test.go b/internal/services/catalog_read_service/test/integration/products/features/deleting_product/v1/commands/delete_product_test.go index 7deae9de..41cbc2cb 100644 --- a/internal/services/catalog_read_service/test/integration/products/features/deleting_product/v1/commands/delete_product_test.go +++ b/internal/services/catalog_read_service/test/integration/products/features/deleting_product/v1/commands/delete_product_test.go @@ -8,7 +8,7 @@ import ( "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/deleting_products/v1/commands" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/test_fixture/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/testfixture/integration" "github.com/mehdihadeli/go-mediatr" uuid "github.com/satori/go.uuid" @@ -23,7 +23,7 @@ func TestDeleteProduct(t *testing.T) { Convey("Deleting Product Feature", t, func() { ctx := context.Background() - integrationTestSharedFixture.InitializeTest() + integrationTestSharedFixture.SetupTest() // https://specflow.org/learn/gherkin/#learn-gherkin // scenario @@ -65,6 +65,6 @@ func TestDeleteProduct(t *testing.T) { }) }) - integrationTestSharedFixture.DisposeTest() + integrationTestSharedFixture.TearDownTest() }) } diff --git a/internal/services/catalog_read_service/test/integration/products/features/deleting_product/v1/events/product_deleted_test.go b/internal/services/catalog_read_service/test/integration/products/features/deleting_product/v1/events/product_deleted_test.go index 8cf628db..bd5b8a0b 100644 --- a/internal/services/catalog_read_service/test/integration/products/features/deleting_product/v1/events/product_deleted_test.go +++ b/internal/services/catalog_read_service/test/integration/products/features/deleting_product/v1/events/product_deleted_test.go @@ -8,12 +8,12 @@ import ( "testing" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging" testUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/utils" externalEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/deleting_products/v1/events/integration_events/external_events" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/models" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/test_fixture/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/testfixture/integration" uuid "github.com/satori/go.uuid" @@ -31,7 +31,7 @@ func TestProductDeleted(t *testing.T) { Convey("Product Deleted Feature", t, func() { ctx := context.Background() // will execute with each subtest - integrationTestSharedFixture.InitializeTest() + integrationTestSharedFixture.SetupTest() // https://specflow.org/learn/gherkin/#learn-gherkin // scenario @@ -105,7 +105,7 @@ func TestProductDeleted(t *testing.T) { }) }) - integrationTestSharedFixture.DisposeTest() + integrationTestSharedFixture.TearDownTest() }) integrationTestSharedFixture.Log.Info("TearDownSuite started") diff --git a/internal/services/catalog_read_service/test/integration/products/features/getting_product_by_id/v1/queries/get_product_by_id_test.go b/internal/services/catalog_read_service/test/integration/products/features/getting_product_by_id/v1/queries/get_product_by_id_test.go index 5f57ce80..ac39eb72 100644 --- a/internal/services/catalog_read_service/test/integration/products/features/getting_product_by_id/v1/queries/get_product_by_id_test.go +++ b/internal/services/catalog_read_service/test/integration/products/features/getting_product_by_id/v1/queries/get_product_by_id_test.go @@ -9,7 +9,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/queries" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/test_fixture/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/testfixture/integration" "github.com/mehdihadeli/go-mediatr" uuid "github.com/satori/go.uuid" @@ -22,7 +22,7 @@ func TestGetProductById(t *testing.T) { ctx := context.Background() Convey("Get Product by ID Feature", t, func() { - integrationTestSharedFixture.InitializeTest() + integrationTestSharedFixture.SetupTest() knownProductID, err := uuid.FromString(integrationTestSharedFixture.Items[0].Id) unknownProductID := uuid.NewV4() @@ -81,6 +81,6 @@ func TestGetProductById(t *testing.T) { }) }) - integrationTestSharedFixture.DisposeTest() + integrationTestSharedFixture.TearDownTest() }) } diff --git a/internal/services/catalog_read_service/test/integration/products/features/getting_products/v1/queries/get_products_handler_test.go b/internal/services/catalog_read_service/test/integration/products/features/getting_products/v1/queries/get_products_handler_test.go index 69e0e70d..36d938f4 100644 --- a/internal/services/catalog_read_service/test/integration/products/features/getting_products/v1/queries/get_products_handler_test.go +++ b/internal/services/catalog_read_service/test/integration/products/features/getting_products/v1/queries/get_products_handler_test.go @@ -10,7 +10,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/getting_products/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/getting_products/v1/queries" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/test_fixture/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/testfixture/integration" "github.com/mehdihadeli/go-mediatr" @@ -22,7 +22,7 @@ func TestGetProducts(t *testing.T) { Convey("Get All Products Feature", t, func() { ctx := context.Background() - integrationTestSharedFixture.InitializeTest() + integrationTestSharedFixture.SetupTest() // https://specflow.org/learn/gherkin/#learn-gherkin // scenario @@ -61,6 +61,6 @@ func TestGetProducts(t *testing.T) { }) }) - integrationTestSharedFixture.DisposeTest() + integrationTestSharedFixture.TearDownTest() }) } diff --git a/internal/services/catalog_read_service/test/integration/products/features/updating_product/v1/commands/update_product_handler_test.go b/internal/services/catalog_read_service/test/integration/products/features/updating_product/v1/commands/update_product_handler_test.go index a87094da..edf612b3 100644 --- a/internal/services/catalog_read_service/test/integration/products/features/updating_product/v1/commands/update_product_handler_test.go +++ b/internal/services/catalog_read_service/test/integration/products/features/updating_product/v1/commands/update_product_handler_test.go @@ -8,7 +8,7 @@ import ( "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/updating_products/v1/commands" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/test_fixture/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/testfixture/integration" "github.com/brianvoe/gofakeit/v6" "github.com/mehdihadeli/go-mediatr" @@ -22,7 +22,7 @@ func TestUpdateProduct(t *testing.T) { Convey("Updating Product Feature", t, func() { ctx := context.Background() - integrationTestSharedFixture.InitializeTest() + integrationTestSharedFixture.SetupTest() // https://specflow.org/learn/gherkin/#learn-gherkin // scenario @@ -66,6 +66,6 @@ func TestUpdateProduct(t *testing.T) { }) }) - integrationTestSharedFixture.DisposeTest() + integrationTestSharedFixture.TearDownTest() }) } diff --git a/internal/services/catalog_read_service/test/integration/products/features/updating_product/v1/events/product_updated_test.go b/internal/services/catalog_read_service/test/integration/products/features/updating_product/v1/events/product_updated_test.go index 37282c39..fbac4a19 100644 --- a/internal/services/catalog_read_service/test/integration/products/features/updating_product/v1/events/product_updated_test.go +++ b/internal/services/catalog_read_service/test/integration/products/features/updating_product/v1/events/product_updated_test.go @@ -8,12 +8,12 @@ import ( "testing" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging" testUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/utils" externalEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/updating_products/v1/events/integration_events/external_events" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/models" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/test_fixture/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/testfixture/integration" "github.com/brianvoe/gofakeit/v6" uuid "github.com/satori/go.uuid" @@ -33,7 +33,7 @@ func TestProductUpdatedConsumer(t *testing.T) { Convey("Product Created Feature", t, func() { ctx := context.Background() - integrationTestSharedFixture.InitializeTest() + integrationTestSharedFixture.SetupTest() // https://specflow.org/learn/gherkin/#learn-gherkin // scenario @@ -143,7 +143,7 @@ func TestProductUpdatedConsumer(t *testing.T) { }, ) - integrationTestSharedFixture.DisposeTest() + integrationTestSharedFixture.TearDownTest() }) integrationTestSharedFixture.Log.Info("TearDownSuite started") diff --git a/internal/services/catalog_write_service/cmd/migration/main.go b/internal/services/catalog_write_service/cmd/migration/main.go index 8cf6b1b6..da9185a1 100644 --- a/internal/services/catalog_write_service/cmd/migration/main.go +++ b/internal/services/catalog_write_service/cmd/migration/main.go @@ -6,14 +6,14 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/goose" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" appconfig "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/config" "github.com/spf13/cobra" diff --git a/internal/services/catalog_write_service/config/app_options.go b/internal/services/catalog_write_service/config/app_options.go index 1f4c65ba..0823bbe3 100644 --- a/internal/services/catalog_write_service/config/app_options.go +++ b/internal/services/catalog_write_service/config/app_options.go @@ -5,7 +5,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/iancoleman/strcase" ) diff --git a/internal/services/catalog_write_service/go.mod b/internal/services/catalog_write_service/go.mod index 5c2c21f2..1d9dfd62 100644 --- a/internal/services/catalog_write_service/go.mod +++ b/internal/services/catalog_write_service/go.mod @@ -7,8 +7,9 @@ replace github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg => ../../ require ( emperror.dev/errors v0.8.1 - github.com/brianvoe/gofakeit/v6 v6.23.2 + github.com/brianvoe/gofakeit/v6 v6.25.0 github.com/gavv/httpexpect/v2 v2.3.1 + github.com/glebarez/sqlite v1.10.0 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 @@ -32,7 +33,7 @@ require ( go.uber.org/fx v1.20.0 google.golang.org/grpc v1.58.2 gopkg.in/khaiql/dbcleaner.v2 v2.3.0 - gorm.io/gorm v1.25.4 + gorm.io/gorm v1.25.5 ) require ( @@ -66,9 +67,11 @@ require ( github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/doug-martin/goqu/v9 v9.18.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/fatih/color v1.15.0 // indirect github.com/fatih/structs v1.0.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect + github.com/glebarez/go-sqlite v1.21.2 // indirect github.com/go-faster/city v1.0.1 // indirect github.com/go-faster/errors v0.6.1 // indirect github.com/go-logr/logr v1.2.4 // indirect @@ -146,6 +149,7 @@ require ( github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 // indirect github.com/redis/go-redis/v9 v9.2.1 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/samber/lo v1.38.1 // indirect github.com/segmentio/asm v1.2.0 // indirect @@ -214,11 +218,14 @@ require ( golang.org/x/tools v0.13.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect - gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gorm.io/driver/postgres v1.5.2 // indirect gorm.io/plugin/opentelemetry v0.1.4 // indirect mellium.im/sasl v0.3.1 // indirect + modernc.org/libc v1.24.1 // indirect + modernc.org/mathutil v1.6.0 // indirect + modernc.org/memory v1.6.0 // indirect + modernc.org/sqlite v1.25.0 // indirect moul.io/http2curl v1.0.1-0.20190925090545-5cd742060b0e // indirect ) diff --git a/internal/services/catalog_write_service/go.sum b/internal/services/catalog_write_service/go.sum index 0fdb0737..1f0d24e9 100644 --- a/internal/services/catalog_write_service/go.sum +++ b/internal/services/catalog_write_service/go.sum @@ -105,8 +105,8 @@ github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/brianvoe/gofakeit/v6 v6.23.2 h1:lVde18uhad5wII/f5RMVFLtdQNE0HaGFuBUXmYKk8i8= -github.com/brianvoe/gofakeit/v6 v6.23.2/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8= +github.com/brianvoe/gofakeit/v6 v6.25.0 h1:ZpFjktOpLZUeF8q223o0rUuXtA+m5qW5srjvVi+JkXk= +github.com/brianvoe/gofakeit/v6 v6.25.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= @@ -188,6 +188,10 @@ github.com/gavv/httpexpect/v2 v2.3.1 h1:sGLlKMn8AuHS9ztK9Sb7AJ7OxIL8v2PcLdyxfKt1 github.com/gavv/httpexpect/v2 v2.3.1/go.mod h1:yOE8m/aqFYQDNrgprMeXgq4YynfN9h1NgcE1+1suV64= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= +github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= +github.com/glebarez/sqlite v1.10.0 h1:u4gt8y7OND/cCei/NMHmfbLxF6xP2wgKcT/BJf2pYkc= +github.com/glebarez/sqlite v1.10.0/go.mod h1:IJ+lfSOmiekhQsFTJRx/lHtGYmCdtAiTaf5wI9u5uHA= github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw= github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw= github.com/go-faster/errors v0.6.1 h1:nNIPOBkprlKzkThvS/0YaX8Zs9KewLCOSFQS5BU06FI= @@ -1247,8 +1251,8 @@ gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0= gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8= gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c= gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I= -gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= -gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= +gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/plugin/opentelemetry v0.1.4 h1:7p0ocWELjSSRI7NCKPW2mVe6h43YPini99sNJcbsTuc= gorm.io/plugin/opentelemetry v0.1.4/go.mod h1:tndJHOdvPT0pyGhOb8E2209eXJCUxhC5UpKw7bGVWeI= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= diff --git a/internal/services/catalog_write_service/internal/products/configurations/mappings/mapping_profile.go b/internal/services/catalog_write_service/internal/products/configurations/mappings/mapping_profile.go index 0a1ba308..466cee39 100644 --- a/internal/services/catalog_write_service/internal/products/configurations/mappings/mapping_profile.go +++ b/internal/services/catalog_write_service/internal/products/configurations/mappings/mapping_profile.go @@ -2,6 +2,7 @@ package mappings import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" productsService "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/grpc/genproto" @@ -20,6 +21,16 @@ func ConfigureProductsMappings() error { return err } + err = mapper.CreateMap[*datamodel.ProductDataModel, *models.Product]() + if err != nil { + return err + } + + err = mapper.CreateMap[*models.Product, *datamodel.ProductDataModel]() + if err != nil { + return err + } + err = mapper.CreateCustomMap[*dtoV1.ProductDto, *productsService.Product]( func(product *dtoV1.ProductDto) *productsService.Product { if product == nil { @@ -39,16 +50,18 @@ func ConfigureProductsMappings() error { return err } - err = mapper.CreateCustomMap(func(product *models.Product) *productsService.Product { - return &productsService.Product{ - ProductId: product.ProductId.String(), - Name: product.Name, - Description: product.Description, - Price: product.Price, - CreatedAt: timestamppb.New(product.CreatedAt), - UpdatedAt: timestamppb.New(product.UpdatedAt), - } - }) + err = mapper.CreateCustomMap( + func(product *models.Product) *productsService.Product { + return &productsService.Product{ + ProductId: product.ProductId.String(), + Name: product.Name, + Description: product.Description, + Price: product.Price, + CreatedAt: timestamppb.New(product.CreatedAt), + UpdatedAt: timestamppb.New(product.UpdatedAt), + } + }, + ) return nil } diff --git a/internal/services/catalog_write_service/internal/products/contracts/catalog_unit_of_work.go b/internal/services/catalog_write_service/internal/products/contracts/catalog_unit_of_work.go deleted file mode 100644 index cd555b8e..00000000 --- a/internal/services/catalog_write_service/internal/products/contracts/catalog_unit_of_work.go +++ /dev/null @@ -1,10 +0,0 @@ -package contracts - -import "context" - -type CatalogUnitOfWorkActionFunc func(catalogContext CatalogContext) error - -type CatalogUnitOfWork interface { - // Do execute the given CatalogUnitOfWorkActionFunc atomically (inside a DB transaction). - Do(ctx context.Context, action CatalogUnitOfWorkActionFunc) error -} diff --git a/internal/services/catalog_write_service/internal/products/contracts/catalogs_context.go b/internal/services/catalog_write_service/internal/products/contracts/catalogs_context.go deleted file mode 100644 index 71c0e83f..00000000 --- a/internal/services/catalog_write_service/internal/products/contracts/catalogs_context.go +++ /dev/null @@ -1,8 +0,0 @@ -package contracts - -// CatalogContext provides access to datastores that can be -// used inside a Unit-of-Work. All data changes done through -// them will be executed atomically (inside a DB transaction). -type CatalogContext interface { - Products() ProductRepository -} diff --git a/internal/services/catalog_write_service/internal/products/data/models/product_data_model.go b/internal/services/catalog_write_service/internal/products/data/models/product_data_model.go new file mode 100644 index 00000000..e9972172 --- /dev/null +++ b/internal/services/catalog_write_service/internal/products/data/models/product_data_model.go @@ -0,0 +1,33 @@ +package models + +import ( + "time" + + "github.com/goccy/go-json" + uuid "github.com/satori/go.uuid" +) + +// https://gorm.io/docs/conventions.html +// https://gorm.io/docs/models.html#gorm-Model + +// ProductDataModel data model +type ProductDataModel struct { + ProductId uuid.UUID `json:"productId" gorm:"primaryKey"` + Name string `json:"name"` + Description string `json:"description"` + Price float64 `json:"price"` + CreatedAt time.Time `json:"createdAt" gorm:"default:current_timestamp"` + UpdatedAt time.Time `json:"updatedAt"` +} + +// https://gorm.io/docs/conventions.html#TableName +// TableName overrides the table name used by ProductDataModel to `products` +func (p *ProductDataModel) TableName() string { + return "products" +} + +func (p *ProductDataModel) String() string { + j, _ := json.Marshal(p) + + return string(j) +} diff --git a/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go b/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go index b9b9ba82..2ae1efdd 100644 --- a/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go +++ b/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go @@ -5,11 +5,11 @@ import ( "fmt" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/data" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres/repository" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" utils2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/repository" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" data2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" diff --git a/internal/services/catalog_write_service/internal/products/data/uow/catalog_context.go b/internal/services/catalog_write_service/internal/products/data/uow/catalog_context.go deleted file mode 100644 index bf4090ef..00000000 --- a/internal/services/catalog_write_service/internal/products/data/uow/catalog_context.go +++ /dev/null @@ -1,13 +0,0 @@ -package uow - -import ( - data2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" -) - -type catalogContext struct { - productRepository data2.ProductRepository -} - -func (c *catalogContext) Products() data2.ProductRepository { - return c.productRepository -} diff --git a/internal/services/catalog_write_service/internal/products/data/uow/catalogs_unit_of_work.go b/internal/services/catalog_write_service/internal/products/data/uow/catalogs_unit_of_work.go deleted file mode 100644 index 3a501434..00000000 --- a/internal/services/catalog_write_service/internal/products/data/uow/catalogs_unit_of_work.go +++ /dev/null @@ -1,60 +0,0 @@ -package uow - -// https://blog.devgenius.io/go-golang-unit-of-work-and-generics-5e9fb00ec996 -// https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application -// https://dev.to/techschoolguru/a-clean-way-to-implement-database-transaction-in-golang-2ba - -import ( - "context" - - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/repositories" - - "gorm.io/gorm" -) - -type catalogUnitOfWork[TContext contracts.CatalogContext] struct { - logger logger.Logger - db *gorm.DB - tracer tracing.AppTracer -} - -func NewCatalogsUnitOfWork( - logger logger.Logger, - db *gorm.DB, - tracer tracing.AppTracer, -) contracts.CatalogUnitOfWork { - return &catalogUnitOfWork[contracts.CatalogContext]{logger: logger, db: db, tracer: tracer} -} - -func (c *catalogUnitOfWork[TContext]) Do( - ctx context.Context, - action contracts.CatalogUnitOfWorkActionFunc, -) error { - // https://gorm.io/docs/transactions.html#Transaction - return c.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { - catalog := &catalogContext{ - productRepository: repositories.NewPostgresProductRepository(c.logger, tx, c.tracer), - } - - defer func() { - r := recover() - if r != nil { - tx.WithContext(ctx).Rollback() - err, _ := r.(error) - if err != nil { - c.logger.Errorf( - "panic tn the transaction, rolling back transaction with panic err: %+v", - err, - ) - } else { - c.logger.Errorf("panic tn the transaction, rolling back transaction with panic message: %+v", r) - } - } - }() - - return action(catalog) - }) -} diff --git a/internal/services/catalog_write_service/internal/products/dtos/v1/fxparams/product_handler_params.go b/internal/services/catalog_write_service/internal/products/dtos/v1/fxparams/product_handler_params.go index a3f135f8..208df77e 100644 --- a/internal/services/catalog_write_service/internal/products/dtos/v1/fxparams/product_handler_params.go +++ b/internal/services/catalog_write_service/internal/products/dtos/v1/fxparams/product_handler_params.go @@ -1,10 +1,10 @@ package fxparams import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/producer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/data/dbcontext" "go.uber.org/fx" ) @@ -13,8 +13,7 @@ type ProductHandlerParams struct { fx.In Log logger.Logger - Uow contracts.CatalogUnitOfWork - ProductRepository contracts.ProductRepository + CatalogsDBContext *dbcontext.CatalogsGormDBContext RabbitmqProducer producer.Producer Tracer tracing.AppTracer } diff --git a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product.go b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product.go index dd0708e9..34c4802d 100644 --- a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product.go +++ b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product.go @@ -38,6 +38,11 @@ func NewCreateProduct( return command, nil } +// IsTxRequest for enabling transactions on the mediatr pipeline +func (c *CreateProduct) IsTxRequest() bool { + return true +} + func (c *CreateProduct) Validate() error { return validation.ValidateStruct( c, diff --git a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_handler.go b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_handler.go index ec317093..7a16da22 100644 --- a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_handler.go @@ -3,13 +3,11 @@ package v1 import ( "context" "fmt" - "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" dtosv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos" @@ -41,6 +39,11 @@ func (c *createProductHandler) Handle( ctx context.Context, command *CreateProduct, ) (*dtos.CreateProductResponseDto, error) { + dbContext, err := c.CatalogsDBContext.WithTx(ctx) + if err != nil { + return nil, err + } + product := &models.Product{ ProductId: command.ProductID, Name: command.Name, @@ -51,64 +54,51 @@ func (c *createProductHandler) Handle( var createProductResult *dtos.CreateProductResponseDto - err := c.Uow.Do( - ctx, - func(catalogContext contracts.CatalogContext) error { - createdProduct, err := catalogContext.Products(). - CreateProduct(ctx, product) - if err != nil { - return customErrors.NewApplicationErrorWrapWithCode( - err, - http.StatusConflict, - "product already exists", - ) - } - productDto, err := mapper.Map[*dtosv1.ProductDto]( - createdProduct, - ) - if err != nil { - return customErrors.NewApplicationErrorWrap( - err, - "error in the mapping ProductDto", - ) - } - - productCreated := integrationevents.NewProductCreatedV1( - productDto, - ) - - err = c.RabbitmqProducer.PublishMessage(ctx, productCreated, nil) - if err != nil { - return customErrors.NewApplicationErrorWrap( - err, - "error in publishing ProductCreated integration_events event", - ) - } - - c.Log.Infow( - fmt.Sprintf( - "ProductCreated message with messageId `%s` published to the rabbitmq broker", - productCreated.MessageId, - ), - logger.Fields{"MessageId": productCreated.MessageId}, - ) - - createProductResult = &dtos.CreateProductResponseDto{ - ProductID: product.ProductId, - } - - c.Log.Infow( - fmt.Sprintf( - "product with id '%s' created", - command.ProductID, - ), - logger.Fields{ - "ProductId": command.ProductID, - "MessageId": productCreated.MessageId, - }, - ) - - return nil + result, err := dbContext.AddProduct(ctx, product) + if err != nil { + return nil, err + } + + productDto, err := mapper.Map[*dtosv1.ProductDto](result) + if err != nil { + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in the mapping ProductDto", + ) + } + + productCreated := integrationevents.NewProductCreatedV1( + productDto, + ) + + err = c.RabbitmqProducer.PublishMessage(ctx, productCreated, nil) + if err != nil { + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in publishing ProductCreated integration_events event", + ) + } + + c.Log.Infow( + fmt.Sprintf( + "ProductCreated message with messageId `%s` published to the rabbitmq broker", + productCreated.MessageId, + ), + logger.Fields{"MessageId": productCreated.MessageId}, + ) + + createProductResult = &dtos.CreateProductResponseDto{ + ProductID: product.ProductId, + } + + c.Log.Infow( + fmt.Sprintf( + "product with id '%s' created", + command.ProductID, + ), + logger.Fields{ + "ProductId": command.ProductID, + "MessageId": productCreated.MessageId, }, ) diff --git a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/events/integrationevents/product_created.go b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/events/integrationevents/product_created.go index da8accf0..53dd041f 100644 --- a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/events/integrationevents/product_created.go +++ b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/events/integrationevents/product_created.go @@ -1,7 +1,7 @@ package integrationevents import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" uuid "github.com/satori/go.uuid" diff --git a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product.go b/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product.go similarity index 82% rename from internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product.go rename to internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product.go index 38dd45cf..c178ab7e 100644 --- a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product.go +++ b/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product.go @@ -20,6 +20,11 @@ func NewDeleteProduct(productID uuid.UUID) (*DeleteProduct, error) { return command, nil } +// IsTxRequest for enabling transactions on the mediatr pipeline +func (c *DeleteProduct) IsTxRequest() bool { + return true +} + func (p *DeleteProduct) Validate() error { return validation.ValidateStruct( p, diff --git a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product_endpoint.go b/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product_endpoint.go similarity index 95% rename from internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product_endpoint.go rename to internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product_endpoint.go index 57aa22b2..9fc67d00 100644 --- a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product_endpoint.go @@ -6,7 +6,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/dtos" "emperror.dev/errors" "github.com/labstack/echo/v4" diff --git a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product_handler.go b/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product_handler.go similarity index 50% rename from internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product_handler.go rename to internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product_handler.go index 9fdb1205..d9b8fef1 100644 --- a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/delete_product_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product_handler.go @@ -3,14 +3,12 @@ package v1 import ( "context" "fmt" - "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" - integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1/events/integrationevents" + integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/events/integrationevents" "github.com/mehdihadeli/go-mediatr" ) @@ -33,48 +31,51 @@ func (c *deleteProductHandler) RegisterHandler() error { ) } +// IsTxRequest for enabling transactions on the mediatr pipeline +func (c *deleteProductHandler) IsTxRequest() bool { + return true +} + func (c *deleteProductHandler) Handle( ctx context.Context, command *DeleteProduct, ) (*mediatr.Unit, error) { - err := c.Uow.Do(ctx, func(catalogContext contracts.CatalogContext) error { - if err := catalogContext.Products().DeleteProductByID(ctx, command.ProductID); err != nil { - return customErrors.NewApplicationErrorWrapWithCode( - err, - http.StatusNotFound, - "product not found", - ) - } + dbContext, err := c.CatalogsDBContext.WithTx(ctx) + if err != nil { + return nil, err + } - productDeleted := integrationEvents.NewProductDeletedV1( - command.ProductID.String(), - ) - err := c.RabbitmqProducer.PublishMessage(ctx, productDeleted, nil) - if err != nil { - return customErrors.NewApplicationErrorWrap( - err, - "error in publishing 'ProductDeleted' message", - ) - } + err = dbContext.DeleteProductByID(ctx, command.ProductID) + if err != nil { + return nil, err + } - c.Log.Infow( - fmt.Sprintf( - "ProductDeleted message with messageId '%s' published to the rabbitmq broker", - productDeleted.MessageId, - ), - logger.Fields{"MessageId": productDeleted.MessageId}, - ) + productDeleted := integrationEvents.NewProductDeletedV1( + command.ProductID.String(), + ) - c.Log.Infow( - fmt.Sprintf( - "product with id '%s' deleted", - command.ProductID, - ), - logger.Fields{"ProductId": command.ProductID}, + if err = c.RabbitmqProducer.PublishMessage(ctx, productDeleted, nil); err != nil { + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in publishing 'ProductDeleted' message", ) + } - return nil - }) + c.Log.Infow( + fmt.Sprintf( + "ProductDeleted message with messageId '%s' published to the rabbitmq broker", + productDeleted.MessageId, + ), + logger.Fields{"MessageId": productDeleted.MessageId}, + ) + + c.Log.Infow( + fmt.Sprintf( + "product with id '%s' deleted", + command.ProductID, + ), + logger.Fields{"ProductId": command.ProductID}, + ) return &mediatr.Unit{}, err } diff --git a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/dtos/delete_product_request_dto.go b/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/dtos/delete_product_request_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/deleting_product/v1/dtos/delete_product_request_dto.go rename to internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/dtos/delete_product_request_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/events/integrationevents/product_deleted.go b/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/events/integrationevents/product_deleted.go similarity index 94% rename from internal/services/catalog_write_service/internal/products/features/deleting_product/v1/events/integrationevents/product_deleted.go rename to internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/events/integrationevents/product_deleted.go index 219aead7..bc449dd6 100644 --- a/internal/services/catalog_write_service/internal/products/features/deleting_product/v1/events/integrationevents/product_deleted.go +++ b/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/events/integrationevents/product_deleted.go @@ -1,7 +1,7 @@ package integrationEvents import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" uuid "github.com/satori/go.uuid" ) diff --git a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_handler.go b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_handler.go index 286ee5f3..2aee6475 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_handler.go @@ -4,10 +4,14 @@ import ( "context" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" dtosv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "github.com/mehdihadeli/go-mediatr" ) @@ -34,16 +38,26 @@ func (c *getProductsHandler) Handle( ctx context.Context, query *GetProducts, ) (*dtos.GetProductsResponseDto, error) { - products, err := c.ProductRepository.GetAllProducts(ctx, query.ListQuery) + products, err := postgresGorm.Paginate[*datamodel.ProductDataModel, *models.Product]( + ctx, + query.ListQuery, + c.CatalogsDBContext.DB, + ) if err != nil { - return nil, err + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in the fetching products", + ) } listResultDto, err := utils.ListResultToListResultDto[*dtosv1.ProductDto]( products, ) if err != nil { - return nil, err + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in the mapping", + ) } c.Log.Info("products fetched") diff --git a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/dtos/get_product_by_id_request_dto.go b/internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/dtos/get_product_by_id_request_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/dtos/get_product_by_id_request_dto.go rename to internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/dtos/get_product_by_id_request_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/dtos/get_product_by_id_response_dto.go b/internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/dtos/get_product_by_id_response_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/dtos/get_product_by_id_response_dto.go rename to internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/dtos/get_product_by_id_response_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id.go b/internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/get_product_by_id.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id.go rename to internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/get_product_by_id.go diff --git a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id_endpoint.go b/internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/get_product_by_id_endpoint.go similarity index 95% rename from internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id_endpoint.go rename to internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/get_product_by_id_endpoint.go index a170bb14..32f8337b 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/get_product_by_id_endpoint.go @@ -6,7 +6,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/dtos" "emperror.dev/errors" "github.com/labstack/echo/v4" diff --git a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id_handler.go b/internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/get_product_by_id_handler.go similarity index 74% rename from internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id_handler.go rename to internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/get_product_by_id_handler.go index c5183b50..36b821cb 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_product_by_id/v1/get_product_by_id_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/get_product_by_id_handler.go @@ -3,7 +3,6 @@ package v1 import ( "context" "fmt" - "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" @@ -11,43 +10,36 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/dtos" "github.com/mehdihadeli/go-mediatr" ) -type getProductByIDHandler struct { +type GetProductByIDHandler struct { fxparams.ProductHandlerParams } func NewGetProductByIDHandler( params fxparams.ProductHandlerParams, ) cqrs.RequestHandlerWithRegisterer[*GetProductById, *dtos.GetProductByIdResponseDto] { - return &getProductByIDHandler{ + return &GetProductByIDHandler{ ProductHandlerParams: params, } } -func (c *getProductByIDHandler) RegisterHandler() error { +func (c *GetProductByIDHandler) RegisterHandler() error { return mediatr.RegisterRequestHandler[*GetProductById, *dtos.GetProductByIdResponseDto]( c, ) } -func (c *getProductByIDHandler) Handle( +func (c *GetProductByIDHandler) Handle( ctx context.Context, query *GetProductById, ) (*dtos.GetProductByIdResponseDto, error) { - product, err := c.ProductRepository.GetProductById(ctx, query.ProductID) + product, err := c.CatalogsDBContext.FindProductByID(ctx, query.ProductID) if err != nil { - return nil, customErrors.NewApplicationErrorWrapWithCode( - err, - http.StatusNotFound, - fmt.Sprintf( - "error in getting product with id %s in the repository", - query.ProductID.String(), - ), - ) + return nil, err } productDto, err := mapper.Map[*dtoV1.ProductDto](product) diff --git a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/dtos/search_products_request_dto.go b/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/dtos/search_products_request_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/searching_product/v1/dtos/search_products_request_dto.go rename to internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/dtos/search_products_request_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/dtos/search_products_response_dto.go b/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/dtos/search_products_response_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/searching_product/v1/dtos/search_products_response_dto.go rename to internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/dtos/search_products_response_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products.go b/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products.go rename to internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products.go diff --git a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products_endpoint.go b/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products_endpoint.go similarity index 96% rename from internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products_endpoint.go rename to internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products_endpoint.go index 1b030304..75ffefeb 100644 --- a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products_endpoint.go @@ -7,7 +7,7 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searching_product/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/dtos" "emperror.dev/errors" "github.com/labstack/echo/v4" diff --git a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products_handler.go b/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products_handler.go similarity index 56% rename from internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products_handler.go rename to internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products_handler.go index 8f344a8d..2eef37bc 100644 --- a/internal/services/catalog_write_service/internal/products/features/searching_product/v1/search_products_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products_handler.go @@ -2,15 +2,25 @@ package v1 import ( "context" + "fmt" + "reflect" + "strings" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + reflectionHelper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/reflectionhelper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searching_product/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" + "github.com/iancoleman/strcase" "github.com/mehdihadeli/go-mediatr" + "gorm.io/gorm" ) type searchProductsHandler struct { @@ -35,10 +45,12 @@ func (c *searchProductsHandler) Handle( ctx context.Context, query *SearchProducts, ) (*dtos.SearchProductsResponseDto, error) { - products, err := c.ProductRepository.SearchProducts( + dbQuery := c.prepareSearchDBQuery(query) + + products, err := gormPostgres.Paginate[*datamodel.ProductDataModel, *models.Product]( ctx, - query.SearchText, query.ListQuery, + dbQuery, ) if err != nil { return nil, customErrors.NewApplicationErrorWrap( @@ -61,3 +73,26 @@ func (c *searchProductsHandler) Handle( return &dtos.SearchProductsResponseDto{Products: listResultDto}, nil } + +func (c *searchProductsHandler) prepareSearchDBQuery( + query *SearchProducts, +) *gorm.DB { + fields := reflectionHelper.GetAllFields( + typeMapper.GetTypeFromGeneric[*datamodel.ProductDataModel](), + ) + + dbQuery := c.CatalogsDBContext.DB + + for _, field := range fields { + if field.Type.Kind() != reflect.String { + continue + } + + dbQuery = dbQuery.Or( + fmt.Sprintf("%s LIKE ?", strcase.ToSnake(field.Name)), + "%"+strings.ToLower(query.SearchText)+"%", + ) + } + + return dbQuery +} diff --git a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product_handler.go b/internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product_handler.go deleted file mode 100644 index a67462a7..00000000 --- a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product_handler.go +++ /dev/null @@ -1,109 +0,0 @@ -package v1 - -import ( - "context" - "fmt" - "net/http" - - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" - dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/events/integrationevents" - - "github.com/mehdihadeli/go-mediatr" -) - -type updateProductHandler struct { - fxparams.ProductHandlerParams - cqrs.HandlerRegisterer -} - -func NewUpdateProductHandler( - params fxparams.ProductHandlerParams, -) cqrs.RequestHandlerWithRegisterer[*UpdateProduct, *mediatr.Unit] { - return &updateProductHandler{ - ProductHandlerParams: params, - } -} - -func (c *updateProductHandler) RegisterHandler() error { - return mediatr.RegisterRequestHandler[*UpdateProduct, *mediatr.Unit]( - c, - ) -} - -func (c *updateProductHandler) Handle( - ctx context.Context, - command *UpdateProduct, -) (*mediatr.Unit, error) { - err := c.Uow.Do(ctx, func(catalogContext contracts.CatalogContext) error { - product, err := catalogContext.Products(). - GetProductById(ctx, command.ProductID) - if err != nil { - return customErrors.NewApplicationErrorWrapWithCode( - err, - http.StatusNotFound, - fmt.Sprintf( - "product with id %s not found", - command.ProductID, - ), - ) - } - - product.Name = command.Name - product.Price = command.Price - product.Description = command.Description - product.UpdatedAt = command.UpdatedAt - - updatedProduct, err := catalogContext.Products(). - UpdateProduct(ctx, product) - if err != nil { - return customErrors.NewApplicationErrorWrap( - err, - "error in updating product in the repository", - ) - } - - productDto, err := mapper.Map[*dto.ProductDto](updatedProduct) - if err != nil { - return customErrors.NewApplicationErrorWrap( - err, - "error in the mapping ProductDto", - ) - } - - productUpdated := integrationevents.NewProductUpdatedV1(productDto) - - err = c.RabbitmqProducer.PublishMessage(ctx, productUpdated, nil) - if err != nil { - return customErrors.NewApplicationErrorWrap( - err, - "error in publishing 'ProductUpdated' message", - ) - } - - c.Log.Infow( - fmt.Sprintf( - "product with id '%s' updated", - command.ProductID, - ), - logger.Fields{"ProductId": command.ProductID}, - ) - - c.Log.Infow( - fmt.Sprintf( - "ProductUpdated message with messageId `%s` published to the rabbitmq broker", - productUpdated.MessageId, - ), - logger.Fields{"MessageId": productUpdated.MessageId}, - ) - - return nil - }) - - return &mediatr.Unit{}, err -} diff --git a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/dtos/update_product_request_dto.go b/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/dtos/update_product_request_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/updating_product/v1/dtos/update_product_request_dto.go rename to internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/dtos/update_product_request_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/events/integrationevents/product_updated.go b/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/events/integrationevents/product_updated.go similarity index 95% rename from internal/services/catalog_write_service/internal/products/features/updating_product/v1/events/integrationevents/product_updated.go rename to internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/events/integrationevents/product_updated.go index 2abfb056..7626a209 100644 --- a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/events/integrationevents/product_updated.go +++ b/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/events/integrationevents/product_updated.go @@ -1,7 +1,7 @@ package integrationevents import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" uuid "github.com/satori/go.uuid" diff --git a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product.go b/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product.go similarity index 50% rename from internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product.go rename to internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product.go index 067bc457..a55072a0 100644 --- a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product.go +++ b/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product.go @@ -15,7 +15,12 @@ type UpdateProduct struct { UpdatedAt time.Time } -func NewUpdateProduct(productID uuid.UUID, name string, description string, price float64) (*UpdateProduct, error) { +func NewUpdateProduct( + productID uuid.UUID, + name string, + description string, + price float64, +) (*UpdateProduct, error) { command := &UpdateProduct{ ProductID: productID, Name: name, @@ -31,10 +36,26 @@ func NewUpdateProduct(productID uuid.UUID, name string, description string, pric return command, nil } +// IsTxRequest for enabling transactions on the mediatr pipeline +func (c *UpdateProduct) IsTxRequest() bool { + return true +} + func (p *UpdateProduct) Validate() error { - return validation.ValidateStruct(p, validation.Field(&p.ProductID, validation.Required), - validation.Field(&p.Name, validation.Required, validation.Length(0, 255)), - validation.Field(&p.Description, validation.Required, validation.Length(0, 5000)), + return validation.ValidateStruct( + p, + validation.Field(&p.ProductID, validation.Required), + 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)) + validation.Field(&p.UpdatedAt, validation.Required), + ) } diff --git a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product_endpoint.go b/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_endpoint.go similarity index 96% rename from internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product_endpoint.go rename to internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_endpoint.go index 57020da4..452147c7 100644 --- a/internal/services/catalog_write_service/internal/products/features/updating_product/v1/update_product_endpoint.go +++ b/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_endpoint.go @@ -6,7 +6,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/dtos" "emperror.dev/errors" "github.com/labstack/echo/v4" diff --git a/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_handler.go b/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_handler.go new file mode 100644 index 00000000..9911b4b5 --- /dev/null +++ b/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_handler.go @@ -0,0 +1,112 @@ +package v1 + +import ( + "context" + "fmt" + "net/http" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" + dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/events/integrationevents" + + "github.com/mehdihadeli/go-mediatr" +) + +type updateProductHandler struct { + fxparams.ProductHandlerParams + cqrs.HandlerRegisterer +} + +func NewUpdateProductHandler( + params fxparams.ProductHandlerParams, +) cqrs.RequestHandlerWithRegisterer[*UpdateProduct, *mediatr.Unit] { + return &updateProductHandler{ + ProductHandlerParams: params, + } +} + +func (c *updateProductHandler) RegisterHandler() error { + return mediatr.RegisterRequestHandler[*UpdateProduct, *mediatr.Unit]( + c, + ) +} + +// IsTxRequest for enabling transactions on the mediatr pipeline +func (c *updateProductHandler) IsTxRequest() bool { + return true +} + +func (c *updateProductHandler) Handle( + ctx context.Context, + command *UpdateProduct, +) (*mediatr.Unit, error) { + dbContext, err := c.CatalogsDBContext.WithTx(ctx) + if err != nil { + return nil, err + } + + product, err := dbContext.FindProductByID(ctx, command.ProductID) + if err != nil { + return nil, customErrors.NewApplicationErrorWrapWithCode( + err, + http.StatusNotFound, + fmt.Sprintf( + "product with id `%s` not found", + command.ProductID, + ), + ) + } + + product.Name = command.Name + product.Price = command.Price + product.Description = command.Description + product.UpdatedAt = command.UpdatedAt + + updatedProduct, err := dbContext.UpdateProduct(ctx, product) + if err != nil { + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in updating product in the repository", + ) + } + + productDto, err := mapper.Map[*dto.ProductDto](updatedProduct) + if err != nil { + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in the mapping ProductDto", + ) + } + + productUpdated := integrationevents.NewProductUpdatedV1(productDto) + + err = c.RabbitmqProducer.PublishMessage(ctx, productUpdated, nil) + if err != nil { + return nil, customErrors.NewApplicationErrorWrap( + err, + "error in publishing 'ProductUpdated' message", + ) + } + + c.Log.Infow( + fmt.Sprintf( + "product with id '%s' updated", + command.ProductID, + ), + logger.Fields{"ProductId": command.ProductID}, + ) + + c.Log.Infow( + fmt.Sprintf( + "ProductUpdated message with messageId `%s` published to the rabbitmq broker", + productUpdated.MessageId, + ), + logger.Fields{"MessageId": productUpdated.MessageId}, + ) + + return &mediatr.Unit{}, err +} diff --git a/internal/services/catalog_write_service/internal/products/mocks/testData/products.go b/internal/services/catalog_write_service/internal/products/mocks/testData/products.go deleted file mode 100644 index 63fb8476..00000000 --- a/internal/services/catalog_write_service/internal/products/mocks/testData/products.go +++ /dev/null @@ -1,27 +0,0 @@ -package testData - -import ( - "time" - - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" - - "github.com/brianvoe/gofakeit/v6" - uuid "github.com/satori/go.uuid" -) - -var Products = []*models.Product{ - { - ProductId: uuid.NewV4(), - Name: gofakeit.Name(), - CreatedAt: time.Now(), - Description: gofakeit.AdjectiveDescriptive(), - Price: gofakeit.Price(100, 1000), - }, - { - ProductId: uuid.NewV4(), - Name: gofakeit.Name(), - CreatedAt: time.Now(), - Description: gofakeit.AdjectiveDescriptive(), - Price: gofakeit.Price(100, 1000), - }, -} diff --git a/internal/services/catalog_write_service/internal/products/models/product.go b/internal/services/catalog_write_service/internal/products/models/product.go index 9611ed70..a7251bb9 100644 --- a/internal/services/catalog_write_service/internal/products/models/product.go +++ b/internal/services/catalog_write_service/internal/products/models/product.go @@ -3,21 +3,15 @@ package models import ( "time" - "github.com/goccy/go-json" uuid "github.com/satori/go.uuid" ) // Product model type Product struct { - ProductId uuid.UUID `json:"productId" gorm:"primaryKey"` - Name string `json:"name"` - Description string `json:"description"` - Price float64 `json:"price"` - CreatedAt time.Time `json:"createdAt"` // https://gorm.io/docs/models.html#gorm-Model - UpdatedAt time.Time `json:"updatedAt"` // https://gorm.io/docs/models.html#gorm-Model -} - -func (p *Product) String() string { - j, _ := json.Marshal(p) - return string(j) + ProductId uuid.UUID + Name string + Description string + Price float64 + CreatedAt time.Time + UpdatedAt time.Time } diff --git a/internal/services/catalog_write_service/internal/products/products_fx.go b/internal/services/catalog_write_service/internal/products/products_fx.go index 25afd4d9..19839f9c 100644 --- a/internal/services/catalog_write_service/internal/products/products_fx.go +++ b/internal/services/catalog_write_service/internal/products/products_fx.go @@ -6,11 +6,11 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/repositories" creatingproductv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1" - deletingproductv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1" - gettingproductbyidv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1" + deletingproductv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1" gettingproductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1" - searchingproductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searching_product/v1" - updatingoroductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1" + gettingproductbyidv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1" + searchingproductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1" + updatingoroductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/grpc" "github.com/labstack/echo/v4" diff --git a/internal/services/catalog_write_service/internal/shared/app/test/test_app.go b/internal/services/catalog_write_service/internal/shared/app/test/test_app.go index 340cdffa..d1d2a172 100644 --- a/internal/services/catalog_write_service/internal/shared/app/test/test_app.go +++ b/internal/services/catalog_write_service/internal/shared/app/test/test_app.go @@ -7,18 +7,18 @@ import ( "time" fxcontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc" config3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" contracts2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/contracts" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/bus" config2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/testcontainer/gorm" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/testcontainer/rabbitmq" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/config" - productcontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/configurations/catalogs" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/data/dbcontext" productsService "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/grpc/genproto" "github.com/stretchr/testify/require" @@ -35,12 +35,11 @@ type TestAppResult struct { RabbitmqOptions *config2.RabbitmqOptions EchoHttpOptions *config3.EchoHttpOptions GormOptions *gormPostgres.GormOptions - CatalogUnitOfWorks productcontracts.CatalogUnitOfWork - ProductRepository productcontracts.ProductRepository Gorm *gorm2.DB ProductServiceClient productsService.ProductsServiceClient GrpcClient grpc.GrpcClient PostgresMigrationRunner contracts2.PostgresMigrationRunner + CatalogsDBContext *dbcontext.CatalogsGormDBContext } func NewTestApp() *TestApp { @@ -77,9 +76,8 @@ func (a *TestApp) Run(t *testing.T) (result *TestAppResult) { logger logger.Logger, rabbitmqOptions *config2.RabbitmqOptions, gormOptions *gormPostgres.GormOptions, - catalogUnitOfWorks productcontracts.CatalogUnitOfWork, - productRepository productcontracts.ProductRepository, gorm *gorm2.DB, + catalogsDBContext *dbcontext.CatalogsGormDBContext, echoOptions *config3.EchoHttpOptions, grpcClient grpc.GrpcClient, postgresMigrationRunner contracts2.PostgresMigrationRunner, @@ -93,9 +91,8 @@ func (a *TestApp) Run(t *testing.T) (result *TestAppResult) { Logger: logger, RabbitmqOptions: rabbitmqOptions, GormOptions: gormOptions, - ProductRepository: productRepository, - CatalogUnitOfWorks: catalogUnitOfWorks, Gorm: gorm, + CatalogsDBContext: catalogsDBContext, EchoHttpOptions: echoOptions, PostgresMigrationRunner: postgresMigrationRunner, ProductServiceClient: productsService.NewProductsServiceClient( diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator.go b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator.go index fb96406e..44145d2f 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator.go +++ b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator.go @@ -6,7 +6,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" echocontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" - contracts2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/contracts" + migrationcontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/infrastructure" @@ -44,7 +44,7 @@ func (ic *CatalogsServiceConfigurator) ConfigureCatalogs() error { // Shared // Catalogs configurations ic.ResolveFunc( - func(gorm *gorm.DB, postgresMigrationRunner contracts2.PostgresMigrationRunner) error { + func(gorm *gorm.DB, postgresMigrationRunner migrationcontracts.PostgresMigrationRunner) error { err := ic.migrateCatalogs(gorm, postgresMigrationRunner) if err != nil { return err diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_fx.go b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_fx.go index 47f89d94..09254c20 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_fx.go +++ b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_fx.go @@ -5,9 +5,9 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/uow" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/infrastructure" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/data" "go.opentelemetry.io/otel/metric" api "go.opentelemetry.io/otel/metric" @@ -20,13 +20,13 @@ var CatalogsServiceModule = fx.Module( // Shared Modules config.Module, infrastructure.Module, + data.Module, // Features Modules products.Module, // Other provides fx.Provide(provideCatalogsMetrics), - fx.Provide(uow.NewCatalogsUnitOfWork), ) // ref: https://github.com/open-telemetry/opentelemetry-go/blob/main/example/prometheus/main.go diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go index 41668319..7e2b362c 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go +++ b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go @@ -3,13 +3,15 @@ package infrastructure import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/pipelines" + loggingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/pipelines" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" - pipelines2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/mediatr/pipelines" + metricspipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/mediatr/pipelines" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" tracingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/mediatr/pipelines" + postgrespipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/mediatr/pipelines" "github.com/mehdihadeli/go-mediatr" + "gorm.io/gorm" ) type InfrastructureConfigurator struct { @@ -26,17 +28,18 @@ func NewInfrastructureConfigurator( func (ic *InfrastructureConfigurator) ConfigInfrastructures() { ic.ResolveFunc( - func(logger logger.Logger, tracer tracing.AppTracer, metrics metrics.AppMetrics) error { + func(l logger.Logger, tracer tracing.AppTracer, metrics metrics.AppMetrics, db *gorm.DB) error { err := mediatr.RegisterRequestPipelineBehaviors( - pipelines.NewLoggingPipeline(logger), + loggingpipelines.NewMediatorLoggingPipeline(l), tracingpipelines.NewMediatorTracingPipeline( tracer, - tracingpipelines.WithLogger(logger), + tracingpipelines.WithLogger(l), ), - pipelines2.NewMediatorMetricsPipeline( + metricspipelines.NewMediatorMetricsPipeline( metrics, - pipelines2.WithLogger(logger), + metricspipelines.WithLogger(l), ), + postgrespipelines.NewMediatorTransactionPipeline(l, db), ) return err diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go index 46c1a139..c259dffe 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go +++ b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go @@ -2,13 +2,13 @@ package infrastructure import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health" customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/goose" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" rabbitmq2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations/rabbitmq" diff --git a/internal/services/catalog_write_service/internal/shared/data/data_fx.go b/internal/services/catalog_write_service/internal/shared/data/data_fx.go new file mode 100644 index 00000000..dfbcd9bd --- /dev/null +++ b/internal/services/catalog_write_service/internal/shared/data/data_fx.go @@ -0,0 +1,18 @@ +package data + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/data/dbcontext" + + "go.uber.org/fx" +) + +// https://uber-go.github.io/fx/modules.html +var Module = fx.Module( + "datafx", + // - order is not important in provide + // - provide can have parameter and will resolve if registered + // - execute its func only if it requested + fx.Provide( + dbcontext.NewCatalogsDBContext, + ), +) diff --git a/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext.go b/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext.go new file mode 100644 index 00000000..e2f7340e --- /dev/null +++ b/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext.go @@ -0,0 +1,231 @@ +package dbcontext + +import ( + "context" + "fmt" + + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/helpers" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" + + uuid "github.com/satori/go.uuid" + "gorm.io/gorm" +) + +type CatalogContextActionFunc func(ctx context.Context, catalogContext *CatalogsGormDBContext) error + +type CatalogsGormDBContext struct { + *gorm.DB + logger logger.Logger +} + +func NewCatalogsDBContext( + db *gorm.DB, + log logger.Logger, +) *CatalogsGormDBContext { + c := &CatalogsGormDBContext{DB: db, logger: log} + + return c +} + +// WithTx creates a transactional DBContext with getting tx-gorm from the ctx +func (c *CatalogsGormDBContext) WithTx( + ctx context.Context, +) (*CatalogsGormDBContext, error) { + tx, err := helpers.GetTxFromContext(ctx) + if err != nil { + return nil, err + } + + return NewCatalogsDBContext(tx, c.logger), nil +} + +func (c *CatalogsGormDBContext) RunInTx( + ctx context.Context, + action CatalogContextActionFunc, +) error { + // https://gorm.io/docs/transactions.html#Transaction + tx := c.WithContext(ctx).Begin() + + c.logger.Info("beginning database transaction") + + gormContext := helpers.SetTxToContext(ctx, tx) + ctx = gormContext + + defer func() { + if r := recover(); r != nil { + tx.WithContext(ctx).Rollback() + + if err, _ := r.(error); err != nil { + c.logger.Errorf( + "panic tn the transaction, rolling back transaction with panic err: %+v", + err, + ) + } else { + c.logger.Errorf("panic tn the transaction, rolling back transaction with panic message: %+v", r) + } + } + }() + + err := action(ctx, c) + if err != nil { + c.logger.Error("rolling back transaction") + tx.WithContext(ctx).Rollback() + + return err + } + + c.logger.Info("committing transaction") + + if err = tx.WithContext(ctx).Commit().Error; err != nil { + c.logger.Errorf("transaction commit error: ", err) + } + + return err +} + +// Extensions for shared and reusable methods. for complex and none-reusable queries we use DBContext directly + +func (c *CatalogsGormDBContext) FindProductByID( + ctx context.Context, + id uuid.UUID, +) (*models.Product, error) { + var productData *datamodel.ProductDataModel + + // https://gorm.io/docs/query.html#Retrieving-objects-with-primary-key + // https://gorm.io/docs/query.html#Struct-amp-Map-Conditions + // https://gorm.io/docs/query.html#Inline-Condition + // https://gorm.io/docs/advanced_query.html + result := c.WithContext(ctx).First(&productData, id) + if result.Error != nil { + return nil, customErrors.NewNotFoundErrorWrap( + result.Error, + fmt.Sprintf( + "product with id `%s` not found in the database", + id.String(), + ), + ) + } + + c.logger.Infof("Number of affected rows are: %d", result.RowsAffected) + + product, err := mapper.Map[*models.Product](productData) + if err != nil { + return nil, customErrors.NewInternalServerErrorWrap( + err, + "error in the mapping Product", + ) + } + + return product, nil +} + +func (c *CatalogsGormDBContext) DeleteProductByID( + ctx context.Context, + id uuid.UUID, +) error { + product, err := c.FindProductByID(ctx, id) + if err != nil { + return customErrors.NewNotFoundErrorWrap( + err, + fmt.Sprintf( + "product with id `%s` not found in the database", + id.String(), + ), + ) + } + + productDataModel, err := mapper.Map[*datamodel.ProductDataModel](product) + if err != nil { + return customErrors.NewInternalServerErrorWrap( + err, + "error in the mapping ProductDataModel", + ) + } + + result := c.WithContext(ctx).Delete(productDataModel, id) + if result.Error != nil { + return customErrors.NewInternalServerErrorWrap( + result.Error, + fmt.Sprintf( + "error in deleting product with id `%s` in the database", + id.String(), + ), + ) + } + + c.logger.Infof("Number of affected rows are: %d", result.RowsAffected) + + return nil +} + +func (c *CatalogsGormDBContext) AddProduct( + ctx context.Context, + product *models.Product, +) (*models.Product, error) { + productDataModel, err := mapper.Map[*datamodel.ProductDataModel](product) + if err != nil { + return nil, customErrors.NewInternalServerErrorWrap( + err, + "error in the mapping ProductDataModel", + ) + } + + // https://gorm.io/docs/create.html + result := c.WithContext(ctx).Create(productDataModel) + if result.Error != nil { + return nil, customErrors.NewConflictErrorWrap( + result.Error, + "product already exists", + ) + } + + c.logger.Infof("Number of affected rows are: %d", result.RowsAffected) + + product, err = mapper.Map[*models.Product](productDataModel) + if err != nil { + return nil, customErrors.NewInternalServerErrorWrap( + err, + "error in the mapping Product", + ) + } + + return product, err +} + +func (c *CatalogsGormDBContext) UpdateProduct( + ctx context.Context, + product *models.Product, +) (*models.Product, error) { + productDataModel, err := mapper.Map[*datamodel.ProductDataModel](product) + if err != nil { + return nil, customErrors.NewInternalServerErrorWrap( + err, + "error in the mapping ProductDataModel", + ) + } + + // https://gorm.io/docs/update.html + result := c.WithContext(ctx).Updates(productDataModel) + if result.Error != nil { + return nil, customErrors.NewInternalServerErrorWrap( + err, + "error in updating the product", + ) + } + + c.logger.Infof("Number of affected rows are: %d", result.RowsAffected) + + product, err = mapper.Map[*models.Product](productDataModel) + if err != nil { + return nil, customErrors.NewInternalServerErrorWrap( + err, + "error in the mapping Product", + ) + } + + return product, err +} diff --git a/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext_test.go b/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext_test.go new file mode 100644 index 00000000..61531ee4 --- /dev/null +++ b/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext_test.go @@ -0,0 +1,212 @@ +package dbcontext + +import ( + "context" + "testing" + "time" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/goose" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations/mappings" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" + + "emperror.dev/errors" + "github.com/brianvoe/gofakeit/v6" + uuid "github.com/satori/go.uuid" + "github.com/stretchr/testify/suite" + "go.uber.org/fx" + "go.uber.org/fx/fxtest" + "gorm.io/gorm" +) + +// Define the suite +type DBContextTestSuite struct { + suite.Suite + items []*datamodel.ProductDataModel + dbContext *CatalogsGormDBContext + app *fxtest.App +} + +// In order for 'go test' to run this suite, we need to create +// a normal test function and pass our suite to suite.Run +func TestDBContextTestSuite(t *testing.T) { + suite.Run(t, new(DBContextTestSuite)) +} + +func (s *DBContextTestSuite) Test_FindProductByID() { + s.Require().NotNil(s.dbContext) + + id := s.items[0].ProductId + + p, err := s.dbContext.FindProductByID( + context.Background(), + id, + ) + s.Require().NoError(err) + s.Require().NotNil(p) + + s.Assert().Equal(p.ProductId, id) +} + +func (s *DBContextTestSuite) Test_DeleteProductByID() { + s.Require().NotNil(s.dbContext) + + id := s.items[0].ProductId + + err := s.dbContext.DeleteProductByID( + context.Background(), + id, + ) + s.Require().NoError(err) + + p, err := s.dbContext.FindProductByID( + context.Background(), + id, + ) + + s.Require().Nil(p) + s.Require().Error(err) +} + +func (s *DBContextTestSuite) Test_CreateProduct() { + s.Require().NotNil(s.dbContext) + + item := &models.Product{ + ProductId: uuid.NewV4(), + Name: gofakeit.Name(), + Description: gofakeit.AdjectiveDescriptive(), + Price: gofakeit.Price(100, 1000), + } + + res, err := s.dbContext.AddProduct(context.Background(), item) + s.Require().NoError(err) + + p, err := s.dbContext.FindProductByID( + context.Background(), + item.ProductId, + ) + s.Require().NoError(err) + s.Require().NotNil(p) + + s.Assert().Equal(p.ProductId, item.ProductId) + s.Assert().Equal(p.ProductId, res.ProductId) +} + +func (s *DBContextTestSuite) Test_UpdateProduct() { + s.Require().NotNil(s.dbContext) + + id := s.items[0].ProductId + + p, err := s.dbContext.FindProductByID( + context.Background(), + id, + ) + s.Require().NoError(err) + + newName := gofakeit.Name() + item := p + item.Name = newName + + res, err := s.dbContext.UpdateProduct(context.Background(), item) + s.Require().NoError(err) + + p2, err := s.dbContext.FindProductByID( + context.Background(), + id, + ) + s.Require().NoError(err) + + s.Assert().Equal(item.Name, p2.Name) + s.Assert().Equal(res.Name, p2.Name) +} + +// TestSuite Hooks +func (s *DBContextTestSuite) SetupTest() { + var gormDBContext *CatalogsGormDBContext + + app := fxtest.New( + s.T(), + config.ModuleFunc(environment.Test), + zap.Module, + fxlog.FxLogger, + core.Module, + gormPostgres.Module, + goose.Module, + fx.Decorate( + func(cfg *gormPostgres.GormOptions) (*gormPostgres.GormOptions, error) { + // using sql-lite in-memory + cfg.UseInMemory = true + + return cfg, nil + }, + ), + fx.Provide( + NewCatalogsDBContext, + ), + fx.Populate(&gormDBContext), + ).RequireStart() + + s.dbContext = gormDBContext + products := s.setupInMemoryContext() + + s.app = app + s.items = products +} + +func (s *DBContextTestSuite) SetupSuite() { + err := mappings.ConfigureProductsMappings() + s.Require().NoError(err) +} + +func (s *DBContextTestSuite) setupInMemoryContext() []*datamodel.ProductDataModel { + err := migrateGorm(s.dbContext.DB) + s.Require().NoError(err) + + res, err := seedData(s.dbContext.DB) + s.Require().NoError(errors.WrapIf(err, "error in seeding data in postgres")) + + return res +} + +func migrateGorm(db *gorm.DB) error { + err := db.AutoMigrate(&datamodel.ProductDataModel{}) + if err != nil { + return err + } + + return nil +} + +func seedData(gormDB *gorm.DB) ([]*datamodel.ProductDataModel, error) { + products := []*datamodel.ProductDataModel{ + { + ProductId: uuid.NewV4(), + Name: gofakeit.Name(), + CreatedAt: time.Now(), + Description: gofakeit.AdjectiveDescriptive(), + Price: gofakeit.Price(100, 1000), + }, + { + ProductId: uuid.NewV4(), + Name: gofakeit.Name(), + CreatedAt: time.Now(), + Description: gofakeit.AdjectiveDescriptive(), + Price: gofakeit.Price(100, 1000), + }, + } + + // migration will do in app configuration + // seed data + err := gormDB.CreateInBatches(products, len(products)).Error + if err != nil { + return nil, errors.Wrap(err, "error in seed database") + } + + return products, nil +} diff --git a/internal/services/catalog_write_service/internal/shared/grpc/product_grpc_service_server.go b/internal/services/catalog_write_service/internal/shared/grpc/product_grpc_service_server.go index b4f96829..094d7c98 100644 --- a/internal/services/catalog_write_service/internal/shared/grpc/product_grpc_service_server.go +++ b/internal/services/catalog_write_service/internal/shared/grpc/product_grpc_service_server.go @@ -10,9 +10,9 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" createProductCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1" createProductDtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos" - getProductByIdQueryV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1" - getProductByIdDtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/dtos" - updateProductCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1" + getProductByIdQueryV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1" + getProductByIdDtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/dtos" + updateProductCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/contracts" productsService "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/grpc/genproto" diff --git a/internal/services/catalog_write_service/internal/shared/test_fixtures/unit_test/unit_test_fixture.go b/internal/services/catalog_write_service/internal/shared/test_fixtures/unit_test/unit_test_fixture.go deleted file mode 100644 index 4d2492f6..00000000 --- a/internal/services/catalog_write_service/internal/shared/test_fixtures/unit_test/unit_test_fixture.go +++ /dev/null @@ -1,116 +0,0 @@ -package unit_test - -import ( - "fmt" - "testing" - - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/default_logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - mocks3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/mocks" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" - dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/mocks/testData" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/mocks" - - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - "go.opentelemetry.io/otel/trace" -) - -type UnitTestSharedFixture struct { - Cfg *config.AppOptions - Log logger.Logger - suite.Suite - Items []*models.Product - Uow *mocks.CatalogUnitOfWork - ProductRepository *mocks.ProductRepository - Bus *mocks3.Bus - Tracer trace.Tracer -} - -func NewUnitTestSharedFixture(t *testing.T) *UnitTestSharedFixture { - // we could use EmptyLogger if we don't want to log anything - log := defaultLogger.GetLogger() - cfg := &config.AppOptions{} - - err := configMapper() - require.NoError(t, err) - - // empty tracer, just for testing - nopetracer := trace.NewNoopTracerProvider() - testTracer := nopetracer.Tracer("test_tracer") - - unit := &UnitTestSharedFixture{ - Cfg: cfg, - Log: log, - Items: testData.Products, - Tracer: testTracer, - } - - return unit -} - -func configMapper() error { - err := mapper.CreateMap[*models.Product, *dto.ProductDto]() - if err != nil { - return err - } - - err = mapper.CreateMap[*dto.ProductDto, *models.Product]() - if err != nil { - return err - } - - return nil -} - -// //////////////Shared Hooks//////////////// -func (c *UnitTestSharedFixture) SetupTest() { - // create new mocks - productRepository := &mocks.ProductRepository{} - bus := &mocks3.Bus{} - uow := &mocks.CatalogUnitOfWork{} - catalogContext := &mocks.CatalogContext{} - - //// or just clear the mocks - //c.Bus.ExpectedCalls = nil - //c.Bus.Calls = nil - //c.Uow.ExpectedCalls = nil - //c.Uow.Calls = nil - //c.ProductRepository.ExpectedCalls = nil - //c.ProductRepository.Calls = nil - - uow.On("Products").Return(productRepository) - catalogContext.On("Products").Return(productRepository) - - var mockUOW *mock.Call - mockUOW = uow.On("Do", mock.Anything, mock.Anything). - Run(func(args mock.Arguments) { - fn, ok := args.Get(1).(contracts.CatalogUnitOfWorkActionFunc) - if !ok { - panic("argument mismatch") - } - fmt.Println(fn) - - mockUOW.Return(fn(catalogContext)) - }) - - mockUOW.Times(1) - bus.On("PublishMessage", mock.Anything, mock.Anything, mock.Anything).Return(nil) - - c.Uow = uow - c.ProductRepository = productRepository - c.Bus = bus -} - -func (c *UnitTestSharedFixture) CleanupMocks() { - c.SetupTest() -} - -func (c *UnitTestSharedFixture) TearDownSuite() { - mapper.ClearMappings() -} diff --git a/internal/services/catalog_write_service/internal/shared/test_fixtures/integration/integration_test_fixture.go b/internal/services/catalog_write_service/internal/shared/testfixtures/integration/integration_test_fixture.go similarity index 85% rename from internal/services/catalog_write_service/internal/shared/test_fixtures/integration/integration_test_fixture.go rename to internal/services/catalog_write_service/internal/shared/testfixtures/integration/integration_test_fixture.go index 94b5526e..4208123f 100644 --- a/internal/services/catalog_write_service/internal/shared/test_fixtures/integration/integration_test_fixture.go +++ b/internal/services/catalog_write_service/internal/shared/testfixtures/integration/integration_test_fixture.go @@ -5,17 +5,17 @@ import ( "testing" "time" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/bus" fxcontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/gorm_postgres" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/bus" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" config2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/testfixture" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/config" - productscontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/app/test" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/data/dbcontext" productsService "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/grpc/genproto" "emperror.dev/errors" @@ -32,15 +32,14 @@ type IntegrationTestSharedFixture struct { Cfg *config.AppOptions Log logger.Logger Bus bus.Bus - CatalogUnitOfWorks productscontracts.CatalogUnitOfWork - ProductRepository productscontracts.ProductRepository + CatalogsDBContext *dbcontext.CatalogsGormDBContext Container fxcontracts.Container DbCleaner dbcleaner.DbCleaner RabbitmqCleaner *rabbithole.Client rabbitmqOptions *config2.RabbitmqOptions Gorm *gorm.DB BaseAddress string - Items []*models.Product + Items []*datamodel.ProductDataModel ProductServiceClient productsService.ProductsServiceClient } @@ -65,8 +64,7 @@ func NewIntegrationTestSharedFixture( Container: result.Container, Cfg: result.Cfg, RabbitmqCleaner: rmqc, - ProductRepository: result.ProductRepository, - CatalogUnitOfWorks: result.CatalogUnitOfWorks, + CatalogsDBContext: result.CatalogsDBContext, Bus: result.Bus, rabbitmqOptions: result.RabbitmqOptions, Gorm: result.Gorm, @@ -77,8 +75,8 @@ func NewIntegrationTestSharedFixture( return shared } -func (i *IntegrationTestSharedFixture) InitializeTest() { - i.Log.Info("InitializeTest started") +func (i *IntegrationTestSharedFixture) SetupTest() { + i.Log.Info("SetupTest started") // seed data in each test res, err := seedData(i.Gorm) @@ -89,8 +87,8 @@ func (i *IntegrationTestSharedFixture) InitializeTest() { i.Items = res } -func (i *IntegrationTestSharedFixture) DisposeTest() { - i.Log.Info("DisposeTest started") +func (i *IntegrationTestSharedFixture) TearDownTest() { + i.Log.Info("TearDownTest started") // cleanup test containers with their hooks if err := i.cleanupRabbitmqData(); err != nil { @@ -137,8 +135,8 @@ func (i *IntegrationTestSharedFixture) cleanupPostgresData() error { return nil } -func seedData(gormDB *gorm.DB) ([]*models.Product, error) { - products := []*models.Product{ +func seedData(gormDB *gorm.DB) ([]*datamodel.ProductDataModel, error) { + products := []*datamodel.ProductDataModel{ { ProductId: uuid.NewV4(), Name: gofakeit.Name(), @@ -165,9 +163,9 @@ func seedData(gormDB *gorm.DB) ([]*models.Product, error) { return products, nil } -func seedAndMigration(gormDB *gorm.DB) ([]*models.Product, error) { +func seedAndMigration(gormDB *gorm.DB) ([]*datamodel.ProductDataModel, error) { // migration - err := gormDB.AutoMigrate(models.Product{}) + err := gormDB.AutoMigrate(datamodel.ProductDataModel{}) if err != nil { return nil, errors.WrapIf(err, "error in seed database") } @@ -206,7 +204,7 @@ func seedAndMigration(gormDB *gorm.DB) ([]*models.Product, error) { return nil, errors.WrapIf(err, "error in seed database") } - result, err := gormPostgres.Paginate[*models.Product]( + result, err := gormPostgres.Paginate[*datamodel.ProductDataModel, *datamodel.ProductDataModel]( context.Background(), utils.NewListQuery(10, 1), gormDB, diff --git a/internal/services/catalog_write_service/internal/shared/testfixtures/unittest/unit_test_fixture.go b/internal/services/catalog_write_service/internal/shared/testfixtures/unittest/unit_test_fixture.go new file mode 100644 index 00000000..a71c350b --- /dev/null +++ b/internal/services/catalog_write_service/internal/shared/testfixtures/unittest/unit_test_fixture.go @@ -0,0 +1,168 @@ +package unittest + +import ( + "context" + "testing" + "time" + + mocks3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/mocks" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/gromlog" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/helpers" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations/mappings" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/data/dbcontext" + + "emperror.dev/errors" + "github.com/brianvoe/gofakeit/v6" + "github.com/glebarez/sqlite" + uuid "github.com/satori/go.uuid" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/suite" + "go.opentelemetry.io/otel/trace" + "gorm.io/gorm" +) + +type UnitTestSharedFixture struct { + Cfg *config.AppOptions + Log logger.Logger + suite.Suite + Products []*datamodel.ProductDataModel + Bus *mocks3.Bus + Tracer trace.Tracer + CatalogDBContext *dbcontext.CatalogsGormDBContext + Ctx context.Context +} + +func NewUnitTestSharedFixture(t *testing.T) *UnitTestSharedFixture { + // we could use EmptyLogger if we don't want to log anything + log := defaultLogger.GetLogger() + cfg := &config.AppOptions{} + + // empty tracer, just for testing + nopetracer := trace.NewNoopTracerProvider() + testTracer := nopetracer.Tracer("test_tracer") + + unit := &UnitTestSharedFixture{ + Cfg: cfg, + Log: log, + Tracer: testTracer, + } + + return unit +} + +// Shared Hooks + +func (c *UnitTestSharedFixture) SetupTest() { + // create new mocks + bus := &mocks3.Bus{} + + bus.On("PublishMessage", mock.Anything, mock.Anything, mock.Anything). + Return(nil) + + dbContext, products := c.createInMemoryDBContext() + + c.Bus = bus + ctx := context.Background() + c.Ctx = ctx + c.CatalogDBContext = dbContext + c.Products = products + + err := mappings.ConfigureProductsMappings() + c.Require().NoError(err) +} + +func (c *UnitTestSharedFixture) TearDownTest() { + mapper.ClearMappings() +} + +func (c *UnitTestSharedFixture) SetupSuite() { +} + +func (c *UnitTestSharedFixture) TearDownSuite() { +} + +func (c *UnitTestSharedFixture) createInMemoryDBContext() (*dbcontext.CatalogsGormDBContext, []*datamodel.ProductDataModel) { + inMemoryGormDB, err := createInMemoryDB() + c.Require().NoError(err) + + dbContext := dbcontext.NewCatalogsDBContext(inMemoryGormDB, c.Log) + + err = migrateGorm(dbContext) + c.Require().NoError(err) + + items, err := seedData(dbContext) + c.Require().NoError(err) + + return dbContext, items +} + +func (c *UnitTestSharedFixture) BeginTx() { + c.Log.Info("starting transaction") + tx := c.CatalogDBContext.Begin() + gormContext := helpers.SetTxToContext(c.Ctx, tx) + c.Ctx = gormContext +} + +func (c *UnitTestSharedFixture) CommitTx() { + tx, err := helpers.GetTxFromContext(c.Ctx) + c.Require().NoError(err) + c.Log.Info("committing transaction") + tx.Commit() +} + +func createInMemoryDB() (*gorm.DB, error) { + // https://gorm.io/docs/connecting_to_the_database.html#SQLite + // https://github.com/glebarez/sqlite + // https://www.connectionstrings.com/sqlite/ + db, err := gorm.Open( + sqlite.Open(":memory:"), + &gorm.Config{ + Logger: gromlog.NewGormCustomLogger(defaultLogger.GetLogger()), + }) + + return db, err +} + +func migrateGorm(dbContext *dbcontext.CatalogsGormDBContext) error { + err := dbContext.DB.AutoMigrate(&datamodel.ProductDataModel{}) + if err != nil { + return err + } + + return nil +} + +func seedData( + dbContext *dbcontext.CatalogsGormDBContext, +) ([]*datamodel.ProductDataModel, error) { + products := []*datamodel.ProductDataModel{ + { + ProductId: uuid.NewV4(), + Name: gofakeit.Name(), + CreatedAt: time.Now(), + Description: gofakeit.AdjectiveDescriptive(), + Price: gofakeit.Price(100, 1000), + }, + { + ProductId: uuid.NewV4(), + Name: gofakeit.Name(), + CreatedAt: time.Now(), + Description: gofakeit.AdjectiveDescriptive(), + Price: gofakeit.Price(100, 1000), + }, + } + + // migration will do in app configuration + // seed data + err := dbContext.DB.CreateInBatches(products, len(products)).Error + if err != nil { + return nil, errors.Wrap(err, "error in seed database") + } + + return products, nil +} diff --git a/internal/services/catalog_write_service/mocks/CatalogUnitOfWork.go b/internal/services/catalog_write_service/mocks/CatalogUnitOfWork.go deleted file mode 100644 index b7964161..00000000 --- a/internal/services/catalog_write_service/mocks/CatalogUnitOfWork.go +++ /dev/null @@ -1,81 +0,0 @@ -// Code generated by mockery v2.30.16. DO NOT EDIT. - -package mocks - -import ( - context "context" - - data "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" - - mock "github.com/stretchr/testify/mock" -) - -// CatalogUnitOfWork is an autogenerated mock type for the CatalogUnitOfWork type -type CatalogUnitOfWork struct { - mock.Mock -} - -type CatalogUnitOfWork_Expecter struct { - mock *mock.Mock -} - -func (_m *CatalogUnitOfWork) EXPECT() *CatalogUnitOfWork_Expecter { - return &CatalogUnitOfWork_Expecter{mock: &_m.Mock} -} - -// Do provides a mock function with given fields: ctx, action -func (_m *CatalogUnitOfWork) Do(ctx context.Context, action data.CatalogUnitOfWorkActionFunc) error { - ret := _m.Called(ctx, action) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, data.CatalogUnitOfWorkActionFunc) error); ok { - r0 = rf(ctx, action) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// CatalogUnitOfWork_Do_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Do' -type CatalogUnitOfWork_Do_Call struct { - *mock.Call -} - -// Do is a helper method to define mock.On call -// - ctx context.Context -// - action data.CatalogUnitOfWorkActionFunc -func (_e *CatalogUnitOfWork_Expecter) Do(ctx interface{}, action interface{}) *CatalogUnitOfWork_Do_Call { - return &CatalogUnitOfWork_Do_Call{Call: _e.mock.On("Do", ctx, action)} -} - -func (_c *CatalogUnitOfWork_Do_Call) Run(run func(ctx context.Context, action data.CatalogUnitOfWorkActionFunc)) *CatalogUnitOfWork_Do_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(data.CatalogUnitOfWorkActionFunc)) - }) - return _c -} - -func (_c *CatalogUnitOfWork_Do_Call) Return(_a0 error) *CatalogUnitOfWork_Do_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *CatalogUnitOfWork_Do_Call) RunAndReturn(run func(context.Context, data.CatalogUnitOfWorkActionFunc) error) *CatalogUnitOfWork_Do_Call { - _c.Call.Return(run) - return _c -} - -// NewCatalogUnitOfWork creates a new instance of CatalogUnitOfWork. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewCatalogUnitOfWork(t interface { - mock.TestingT - Cleanup(func()) -}) *CatalogUnitOfWork { - mock := &CatalogUnitOfWork{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/internal/services/catalog_write_service/mocks/CatalogUnitOfWorkActionFunc.go b/internal/services/catalog_write_service/mocks/CatalogUnitOfWorkActionFunc.go deleted file mode 100644 index 8e1fccec..00000000 --- a/internal/services/catalog_write_service/mocks/CatalogUnitOfWorkActionFunc.go +++ /dev/null @@ -1,78 +0,0 @@ -// Code generated by mockery v2.30.16. DO NOT EDIT. - -package mocks - -import ( - data "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" - - mock "github.com/stretchr/testify/mock" -) - -// CatalogUnitOfWorkActionFunc is an autogenerated mock type for the CatalogUnitOfWorkActionFunc type -type CatalogUnitOfWorkActionFunc struct { - mock.Mock -} - -type CatalogUnitOfWorkActionFunc_Expecter struct { - mock *mock.Mock -} - -func (_m *CatalogUnitOfWorkActionFunc) EXPECT() *CatalogUnitOfWorkActionFunc_Expecter { - return &CatalogUnitOfWorkActionFunc_Expecter{mock: &_m.Mock} -} - -// Execute provides a mock function with given fields: catalogContext -func (_m *CatalogUnitOfWorkActionFunc) Execute(catalogContext data.CatalogContext) error { - ret := _m.Called(catalogContext) - - var r0 error - if rf, ok := ret.Get(0).(func(data.CatalogContext) error); ok { - r0 = rf(catalogContext) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// CatalogUnitOfWorkActionFunc_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' -type CatalogUnitOfWorkActionFunc_Execute_Call struct { - *mock.Call -} - -// Execute is a helper method to define mock.On call -// - catalogContext data.CatalogContext -func (_e *CatalogUnitOfWorkActionFunc_Expecter) Execute(catalogContext interface{}) *CatalogUnitOfWorkActionFunc_Execute_Call { - return &CatalogUnitOfWorkActionFunc_Execute_Call{Call: _e.mock.On("Execute", catalogContext)} -} - -func (_c *CatalogUnitOfWorkActionFunc_Execute_Call) Run(run func(catalogContext data.CatalogContext)) *CatalogUnitOfWorkActionFunc_Execute_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(data.CatalogContext)) - }) - return _c -} - -func (_c *CatalogUnitOfWorkActionFunc_Execute_Call) Return(_a0 error) *CatalogUnitOfWorkActionFunc_Execute_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *CatalogUnitOfWorkActionFunc_Execute_Call) RunAndReturn(run func(data.CatalogContext) error) *CatalogUnitOfWorkActionFunc_Execute_Call { - _c.Call.Return(run) - return _c -} - -// NewCatalogUnitOfWorkActionFunc creates a new instance of CatalogUnitOfWorkActionFunc. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewCatalogUnitOfWorkActionFunc(t interface { - mock.TestingT - Cleanup(func()) -}) *CatalogUnitOfWorkActionFunc { - mock := &CatalogUnitOfWorkActionFunc{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/internal/services/catalog_write_service/test/end_to_end/products/features/creating_product/v1/create_product_test.go b/internal/services/catalog_write_service/test/endtoend/products/features/creatingproduct/v1/create_product_test.go similarity index 94% rename from internal/services/catalog_write_service/test/end_to_end/products/features/creating_product/v1/create_product_test.go rename to internal/services/catalog_write_service/test/endtoend/products/features/creatingproduct/v1/create_product_test.go index e37207fb..33ad5dd6 100644 --- a/internal/services/catalog_write_service/test/end_to_end/products/features/creating_product/v1/create_product_test.go +++ b/internal/services/catalog_write_service/test/endtoend/products/features/creatingproduct/v1/create_product_test.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" "github.com/brianvoe/gofakeit/v6" "github.com/gavv/httpexpect/v2" @@ -36,12 +36,12 @@ var _ = Describe("CreateProduct Feature", func() { ctx = context.Background() By("Seeding the required data") - integrationFixture.InitializeTest() + integrationFixture.SetupTest() }) _ = AfterEach(func() { By("Cleanup test data") - integrationFixture.DisposeTest() + integrationFixture.TearDownTest() }) // "Scenario" step for testing the create product API with valid input diff --git a/internal/services/catalog_write_service/test/end_to_end/products/features/deleting_product/v1/delete_product_test.go b/internal/services/catalog_write_service/test/endtoend/products/features/deletingproduct/v1/delete_product_test.go similarity index 93% rename from internal/services/catalog_write_service/test/end_to_end/products/features/deleting_product/v1/delete_product_test.go rename to internal/services/catalog_write_service/test/endtoend/products/features/deletingproduct/v1/delete_product_test.go index 1ce96a17..1f9a52c3 100644 --- a/internal/services/catalog_write_service/test/end_to_end/products/features/deleting_product/v1/delete_product_test.go +++ b/internal/services/catalog_write_service/test/endtoend/products/features/deletingproduct/v1/delete_product_test.go @@ -8,7 +8,7 @@ import ( "net/http" "testing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" "github.com/gavv/httpexpect/v2" uuid "github.com/satori/go.uuid" @@ -35,14 +35,14 @@ var _ = Describe("Delete Product Feature", func() { ctx = context.Background() By("Seeding the required data") - integrationFixture.InitializeTest() + integrationFixture.SetupTest() id = integrationFixture.Items[0].ProductId }) _ = AfterEach(func() { By("Cleanup test data") - integrationFixture.DisposeTest() + integrationFixture.TearDownTest() }) // "Scenario" step for testing the delete product API with valid input diff --git a/internal/services/catalog_write_service/test/end_to_end/products/features/getting_product_by_id/v1/get_product_by_id_test.go b/internal/services/catalog_write_service/test/endtoend/products/features/gettingproductbyid/v1/get_product_by_id_test.go similarity index 93% rename from internal/services/catalog_write_service/test/end_to_end/products/features/getting_product_by_id/v1/get_product_by_id_test.go rename to internal/services/catalog_write_service/test/endtoend/products/features/gettingproductbyid/v1/get_product_by_id_test.go index 509ce3ab..dc035dea 100644 --- a/internal/services/catalog_write_service/test/end_to_end/products/features/getting_product_by_id/v1/get_product_by_id_test.go +++ b/internal/services/catalog_write_service/test/endtoend/products/features/gettingproductbyid/v1/get_product_by_id_test.go @@ -8,7 +8,7 @@ import ( "net/http" "testing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" "github.com/gavv/httpexpect/v2" uuid "github.com/satori/go.uuid" @@ -35,14 +35,14 @@ var _ = Describe("Get Product By Id Feature", func() { ctx = context.Background() By("Seeding the required data") - integrationFixture.InitializeTest() + integrationFixture.SetupTest() id = integrationFixture.Items[0].ProductId }) _ = AfterEach(func() { By("Cleanup test data") - integrationFixture.DisposeTest() + integrationFixture.TearDownTest() }) // "Scenario" step for testing the get product by ID API with a valid ID diff --git a/internal/services/catalog_write_service/test/end_to_end/products/features/getting_products/v1/get_products_test.go b/internal/services/catalog_write_service/test/endtoend/products/features/gettingproducts/v1/get_products_test.go similarity index 89% rename from internal/services/catalog_write_service/test/end_to_end/products/features/getting_products/v1/get_products_test.go rename to internal/services/catalog_write_service/test/endtoend/products/features/gettingproducts/v1/get_products_test.go index f125635e..bd6b582a 100644 --- a/internal/services/catalog_write_service/test/end_to_end/products/features/getting_products/v1/get_products_test.go +++ b/internal/services/catalog_write_service/test/endtoend/products/features/gettingproducts/v1/get_products_test.go @@ -8,7 +8,7 @@ import ( "net/http" "testing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" "github.com/gavv/httpexpect/v2" @@ -31,12 +31,12 @@ var _ = Describe("Get All Products Feature", func() { ctx = context.Background() By("Seeding the required data") - integrationFixture.InitializeTest() + integrationFixture.SetupTest() }) _ = AfterEach(func() { By("Cleanup test data") - integrationFixture.DisposeTest() + integrationFixture.TearDownTest() }) // "Scenario" step for testing the get all products API diff --git a/internal/services/catalog_write_service/test/end_to_end/products/features/searching_product/v1/search_products_test.go b/internal/services/catalog_write_service/test/endtoend/products/features/searchingproduct/v1/search_products_test.go similarity index 90% rename from internal/services/catalog_write_service/test/end_to_end/products/features/searching_product/v1/search_products_test.go rename to internal/services/catalog_write_service/test/endtoend/products/features/searchingproduct/v1/search_products_test.go index 521374b8..461ff801 100644 --- a/internal/services/catalog_write_service/test/end_to_end/products/features/searching_product/v1/search_products_test.go +++ b/internal/services/catalog_write_service/test/endtoend/products/features/searchingproduct/v1/search_products_test.go @@ -8,7 +8,7 @@ import ( "net/http" "testing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" "github.com/gavv/httpexpect/v2" @@ -31,12 +31,12 @@ var _ = Describe("Search Products Feature", func() { ctx = context.Background() By("Seeding the required data") - integrationFixture.InitializeTest() + integrationFixture.SetupTest() }) _ = AfterEach(func() { By("Cleanup test data") - integrationFixture.DisposeTest() + integrationFixture.TearDownTest() }) // "Scenario" step for testing the search products API diff --git a/internal/services/catalog_write_service/test/end_to_end/products/features/updating_product/v1/update_product_test.go b/internal/services/catalog_write_service/test/endtoend/products/features/updatingproduct/v1/update_product_test.go similarity index 92% rename from internal/services/catalog_write_service/test/end_to_end/products/features/updating_product/v1/update_product_test.go rename to internal/services/catalog_write_service/test/endtoend/products/features/updatingproduct/v1/update_product_test.go index e8db665e..fc66699a 100644 --- a/internal/services/catalog_write_service/test/end_to_end/products/features/updating_product/v1/update_product_test.go +++ b/internal/services/catalog_write_service/test/endtoend/products/features/updatingproduct/v1/update_product_test.go @@ -8,8 +8,8 @@ import ( "net/http" "testing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/dtos" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" "github.com/brianvoe/gofakeit/v6" "github.com/gavv/httpexpect/v2" @@ -38,13 +38,13 @@ var _ = Describe("UpdateProductE2ETest Suite", func() { ctx = context.Background() By("Seeding the required data") - integrationFixture.InitializeTest() + integrationFixture.SetupTest() id = integrationFixture.Items[0].ProductId }) _ = AfterEach(func() { By("Cleanup test data") - integrationFixture.DisposeTest() + integrationFixture.TearDownTest() }) // "Scenario" step for testing the update product API with valid input diff --git a/internal/services/catalog_write_service/test/end_to_end/products/grpc/product_grpc_service_server_test.go b/internal/services/catalog_write_service/test/endtoend/products/grpc/product_grpc_service_server_test.go similarity index 94% rename from internal/services/catalog_write_service/test/end_to_end/products/grpc/product_grpc_service_server_test.go rename to internal/services/catalog_write_service/test/endtoend/products/grpc/product_grpc_service_server_test.go index 0f543601..6bc06f19 100644 --- a/internal/services/catalog_write_service/test/end_to_end/products/grpc/product_grpc_service_server_test.go +++ b/internal/services/catalog_write_service/test/endtoend/products/grpc/product_grpc_service_server_test.go @@ -8,7 +8,7 @@ import ( "testing" productService "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/grpc/genproto" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" "github.com/brianvoe/gofakeit/v6" uuid "github.com/satori/go.uuid" @@ -35,14 +35,14 @@ var _ = Describe("Product Grpc Service Feature", func() { ctx = context.Background() By("Seeding the required data") - integrationFixture.InitializeTest() + integrationFixture.SetupTest() id = integrationFixture.Items[0].ProductId }) _ = AfterEach(func() { By("Cleanup test data") - integrationFixture.DisposeTest() + integrationFixture.TearDownTest() }) // "Scenario" step for testing the creation of a product with valid data in the database diff --git a/internal/services/catalog_write_service/test/integration/products/data/repositories/pg_product_repository_integration_test.go b/internal/services/catalog_write_service/test/integration/products/data/repositories/pg_product_repository_integration_test.go index 6f7f4d3a..b8b8fa4b 100644 --- a/internal/services/catalog_write_service/test/integration/products/data/repositories/pg_product_repository_integration_test.go +++ b/internal/services/catalog_write_service/test/integration/products/data/repositories/pg_product_repository_integration_test.go @@ -11,7 +11,7 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" "github.com/brianvoe/gofakeit/v6" uuid "github.com/satori/go.uuid" @@ -42,14 +42,14 @@ var _ = Describe("Product Repository Suite", func() { _ = BeforeEach(func() { By("Seeding the required data") - integrationFixture.InitializeTest() + integrationFixture.SetupTest() id = integrationFixture.Items[0].ProductId }) _ = AfterEach(func() { By("Cleanup test data") - integrationFixture.DisposeTest() + integrationFixture.TearDownTest() }) _ = BeforeSuite(func() { diff --git a/internal/services/catalog_write_service/test/integration/products/data/uow/catalogs_unit_of_work_integration_test.go b/internal/services/catalog_write_service/test/integration/products/data/uow/catalogs_unit_of_work_integration_test.go index cac04ee5..d4045033 100644 --- a/internal/services/catalog_write_service/test/integration/products/data/uow/catalogs_unit_of_work_integration_test.go +++ b/internal/services/catalog_write_service/test/integration/products/data/uow/catalogs_unit_of_work_integration_test.go @@ -11,7 +11,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" data2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" "emperror.dev/errors" "github.com/brianvoe/gofakeit/v6" @@ -40,12 +40,12 @@ var _ = Describe("CatalogsUnitOfWork Feature", func() { _ = BeforeEach(func() { ctx = context.Background() By("Seeding the required data") - integrationFixture.InitializeTest() + integrationFixture.SetupTest() }) _ = AfterEach(func() { By("Cleanup test data") - integrationFixture.DisposeTest() + integrationFixture.TearDownTest() }) // "Scenario" step for testing a UnitOfWork action that should roll back on error diff --git a/internal/services/catalog_write_service/test/integration/products/features/creating_product/v1/create_product_test.go b/internal/services/catalog_write_service/test/integration/products/features/creating_product/v1/create_product_test.go deleted file mode 100644 index d68e0bcc..00000000 --- a/internal/services/catalog_write_service/test/integration/products/features/creating_product/v1/create_product_test.go +++ /dev/null @@ -1,197 +0,0 @@ -//go:build integration -// +build integration - -package v1 - -import ( - "context" - "net/http" - "testing" - "time" - - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/hypothesis" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging" - createProductCommand "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos" - integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/events/integrationevents" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" - - "github.com/brianvoe/gofakeit/v6" - "github.com/mehdihadeli/go-mediatr" - uuid "github.com/satori/go.uuid" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var integrationFixture *integration.IntegrationTestSharedFixture - -func TestCreateProduct(t *testing.T) { - RegisterFailHandler(Fail) - integrationFixture = integration.NewIntegrationTestSharedFixture(t) - RunSpecs(t, "Create Product Integration Tests") -} - -// https://specflow.org/learn/gherkin/#learn-gherkin -// scenario -var _ = Describe("Creating Product Feature", func() { - var ( - ctx context.Context - err error - command *createProductCommand.CreateProduct - result *dtos.CreateProductResponseDto - createdProduct *models.Product - id uuid.UUID - shouldPublish hypothesis.Hypothesis[*integrationEvents.ProductCreatedV1] - ) - - _ = BeforeEach(func() { - By("Seeding the required data") - integrationFixture.InitializeTest() - - id = integrationFixture.Items[0].ProductId - }) - - _ = AfterEach(func() { - By("Cleanup test data") - integrationFixture.DisposeTest() - }) - - _ = BeforeSuite(func() { - ctx = context.Background() - - // in test mode we set rabbitmq `AutoStart=false` in configuration in rabbitmqOptions, so we should run rabbitmq bus manually - err = integrationFixture.Bus.Start(context.Background()) - Expect(err).ShouldNot(HaveOccurred()) - - // wait for consumers ready to consume before publishing messages, preparation background workers takes a bit time (for preventing messages lost) - time.Sleep(1 * time.Second) - }) - - _ = AfterSuite(func() { - integrationFixture.Log.Info("TearDownSuite started") - err := integrationFixture.Bus.Stop() - Expect(err).ShouldNot(HaveOccurred()) - time.Sleep(1 * time.Second) - }) - - // "Scenario" step for testing creating a new product - Describe("Creating a new product and saving it to the database when product doesn't exists", func() { - Context("Given new product doesn't exists in the system", func() { - BeforeEach(func() { - command, err = createProductCommand.NewCreateProduct( - gofakeit.Name(), - gofakeit.AdjectiveDescriptive(), - gofakeit.Price(150, 6000), - ) - Expect(err).ToNot(HaveOccurred()) - Expect(command).ToNot(BeNil()) - }) - - When("the CreateProduct command is executed for non-existing product", func() { - BeforeEach(func() { - result, err = mediatr.Send[*createProductCommand.CreateProduct, *dtos.CreateProductResponseDto]( - ctx, - command, - ) - }) - - It("Should create the product successfully", func() { - Expect(err).NotTo(HaveOccurred()) - Expect(result).NotTo(BeNil()) - }) - - It("Should have a non-empty product ID matching the command ID", func() { - Expect(result.ProductID).To(Equal(command.ProductID)) - }) - - It("Should be able to retrieve the product from the database", func() { - createdProduct, err = integrationFixture.ProductRepository.GetProductById( - ctx, - result.ProductID, - ) - Expect(err).NotTo(HaveOccurred()) - - Expect(result).NotTo(BeNil()) - Expect(command.ProductID).To(Equal(result.ProductID)) - Expect(createdProduct).NotTo(BeNil()) - }) - }) - }) - }) - - // "Scenario" step for testing creating a product with duplicate data - Describe("Creating a new product with duplicate data and already exists product", func() { - Context("Given product already exists in the system", func() { - BeforeEach(func() { - command = &createProductCommand.CreateProduct{ - Name: gofakeit.Name(), - Description: gofakeit.AdjectiveDescriptive(), - Price: gofakeit.Price(150, 6000), - ProductID: id, - } - }) - - When("the CreateProduct command is executed for existing product", func() { - BeforeEach(func() { - result, err = mediatr.Send[*createProductCommand.CreateProduct, *dtos.CreateProductResponseDto]( - ctx, - command, - ) - }) - - It("Should return an error indicating duplicate record", func() { - Expect(err).To(HaveOccurred()) - Expect(customErrors.IsApplicationError(err, http.StatusConflict)).To(BeTrue()) - }) - - It("Should not return a result", func() { - Expect(result).To(BeNil()) - }) - }) - }) - }) - - // "Scenario" step for testing creating a product with duplicate data - Describe("Publishing ProductCreated event to the broker when product saved successfully", func() { - Context("Given new product doesn't exists in the system", func() { - BeforeEach(func() { - shouldPublish = messaging.ShouldProduced[*integrationEvents.ProductCreatedV1]( - ctx, - integrationFixture.Bus, - nil, - ) - command, err = createProductCommand.NewCreateProduct( - gofakeit.Name(), - gofakeit.AdjectiveDescriptive(), - gofakeit.Price(150, 6000), - ) - Expect(err).ToNot(HaveOccurred()) - }) - - When("CreateProduct command is executed for non-existing product", func() { - BeforeEach(func() { - result, err = mediatr.Send[*createProductCommand.CreateProduct, *dtos.CreateProductResponseDto]( - ctx, - command, - ) - }) - - It("Should return no error", func() { - Expect(err).ToNot(HaveOccurred()) - }) - - It("Should return not nil result", func() { - Expect(result).ToNot(BeNil()) - }) - - It("Should publish ProductCreated event to the broker", func() { - // ensuring message published to the rabbitmq broker - shouldPublish.Validate(ctx, "there is no published message", time.Second*30) - }) - }) - }) - }) -}) diff --git a/internal/services/catalog_write_service/test/integration/products/features/creatingproduct/v1/create_product_test.go b/internal/services/catalog_write_service/test/integration/products/features/creatingproduct/v1/create_product_test.go new file mode 100644 index 00000000..88748d75 --- /dev/null +++ b/internal/services/catalog_write_service/test/integration/products/features/creatingproduct/v1/create_product_test.go @@ -0,0 +1,243 @@ +//go:build integration +// +build integration + +package v1 + +import ( + "context" + "testing" + "time" + + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/hypothesis" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging" + createProductCommand "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos" + integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/events/integrationevents" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" + + "github.com/brianvoe/gofakeit/v6" + "github.com/mehdihadeli/go-mediatr" + uuid "github.com/satori/go.uuid" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var integrationFixture *integration.IntegrationTestSharedFixture + +func TestCreateProduct(t *testing.T) { + RegisterFailHandler(Fail) + integrationFixture = integration.NewIntegrationTestSharedFixture(t) + RunSpecs(t, "Create Product Integration Tests") +} + +// https://specflow.org/learn/gherkin/#learn-gherkin +// scenario +var _ = Describe("Creating Product Feature", func() { + var ( + ctx context.Context + err error + command *createProductCommand.CreateProduct + result *dtos.CreateProductResponseDto + createdProduct *models.Product + id uuid.UUID + shouldPublish hypothesis.Hypothesis[*integrationEvents.ProductCreatedV1] + ) + + _ = BeforeEach(func() { + By("Seeding the required data") + // call base SetupTest hook before running child hook + integrationFixture.SetupTest() + + // child hook codes should be here + id = integrationFixture.Items[0].ProductId + }) + + _ = AfterEach(func() { + By("Cleanup test data") + // call base TearDownTest hook before running child hook + integrationFixture.TearDownTest() + + // child hook codes should be here + }) + + _ = BeforeSuite(func() { + ctx = context.Background() + + // in test mode we set rabbitmq `AutoStart=false` in configuration in rabbitmqOptions, so we should run rabbitmq bus manually + err = integrationFixture.Bus.Start(context.Background()) + Expect(err).ShouldNot(HaveOccurred()) + + // wait for consumers ready to consume before publishing messages, preparation background workers takes a bit time (for preventing messages lost) + time.Sleep(1 * time.Second) + }) + + _ = AfterSuite(func() { + integrationFixture.Log.Info("TearDownSuite started") + err := integrationFixture.Bus.Stop() + Expect(err).ShouldNot(HaveOccurred()) + time.Sleep(1 * time.Second) + }) + + // "Scenario" step for testing creating a new product + Describe( + "Creating a new product and saving it to the database when product doesn't exists", + func() { + Context("Given new product doesn't exists in the system", func() { + BeforeEach(func() { + command, err = createProductCommand.NewCreateProduct( + gofakeit.Name(), + gofakeit.AdjectiveDescriptive(), + gofakeit.Price(150, 6000), + ) + Expect(err).ToNot(HaveOccurred()) + Expect(command).ToNot(BeNil()) + }) + + When( + "the CreateProduct command is executed for non-existing product", + func() { + BeforeEach(func() { + result, err = mediatr.Send[*createProductCommand.CreateProduct, *dtos.CreateProductResponseDto]( + ctx, + command, + ) + }) + + It("Should create the product successfully", func() { + Expect(err).NotTo(HaveOccurred()) + Expect(result).NotTo(BeNil()) + }) + + It( + "Should have a non-empty product ID matching the command ID", + func() { + Expect( + result.ProductID, + ).To(Equal(command.ProductID)) + }, + ) + + It( + "Should be able to retrieve the product from the database", + func() { + createdProduct, err = integrationFixture.CatalogsDBContext.FindProductByID( + ctx, + result.ProductID, + ) + Expect(err).NotTo(HaveOccurred()) + + Expect(result).NotTo(BeNil()) + Expect( + command.ProductID, + ).To(Equal(result.ProductID)) + Expect(createdProduct).NotTo(BeNil()) + }, + ) + }, + ) + }) + }, + ) + + // "Scenario" step for testing creating a product with duplicate data + Describe( + "Creating a new product with duplicate data and already exists product", + func() { + Context("Given product already exists in the system", func() { + BeforeEach(func() { + command = &createProductCommand.CreateProduct{ + Name: gofakeit.Name(), + Description: gofakeit.AdjectiveDescriptive(), + Price: gofakeit.Price(150, 6000), + ProductID: id, + } + }) + + When( + "the CreateProduct command is executed for existing product", + func() { + BeforeEach(func() { + result, err = mediatr.Send[*createProductCommand.CreateProduct, *dtos.CreateProductResponseDto]( + ctx, + command, + ) + }) + + It( + "Should return an error indicating duplicate record", + func() { + Expect(err).To(HaveOccurred()) + Expect( + customErrors.IsConflictError( + err, + ), + ).To(BeTrue()) + }, + ) + + It("Should not return a result", func() { + Expect(result).To(BeNil()) + }) + }, + ) + }) + }, + ) + + // "Scenario" step for testing creating a product with duplicate data + Describe( + "Publishing ProductCreated event to the broker when product saved successfully", + func() { + Context("Given new product doesn't exists in the system", func() { + BeforeEach(func() { + shouldPublish = messaging.ShouldProduced[*integrationEvents.ProductCreatedV1]( + ctx, + integrationFixture.Bus, + nil, + ) + command, err = createProductCommand.NewCreateProduct( + gofakeit.Name(), + gofakeit.AdjectiveDescriptive(), + gofakeit.Price(150, 6000), + ) + Expect(err).ToNot(HaveOccurred()) + }) + + When( + "CreateProduct command is executed for non-existing product", + func() { + BeforeEach(func() { + result, err = mediatr.Send[*createProductCommand.CreateProduct, *dtos.CreateProductResponseDto]( + ctx, + command, + ) + }) + + It("Should return no error", func() { + Expect(err).ToNot(HaveOccurred()) + }) + + It("Should return not nil result", func() { + Expect(result).ToNot(BeNil()) + }) + + It( + "Should publish ProductCreated event to the broker", + func() { + // ensuring message published to the rabbitmq broker + shouldPublish.Validate( + ctx, + "there is no published message", + time.Second*30, + ) + }, + ) + }, + ) + }) + }, + ) +}) diff --git a/internal/services/catalog_write_service/test/integration/products/features/deleting_product/v1/delete_product_test.go b/internal/services/catalog_write_service/test/integration/products/features/deletingproduct/v1/delete_product_test.go similarity index 52% rename from internal/services/catalog_write_service/test/integration/products/features/deleting_product/v1/delete_product_test.go rename to internal/services/catalog_write_service/test/integration/products/features/deletingproduct/v1/delete_product_test.go index fbebfc0c..80d20531 100644 --- a/internal/services/catalog_write_service/test/integration/products/features/deleting_product/v1/delete_product_test.go +++ b/internal/services/catalog_write_service/test/integration/products/features/deletingproduct/v1/delete_product_test.go @@ -5,16 +5,16 @@ package v1 import ( "context" - "net/http" + "fmt" "testing" "time" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/hypothesis" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging" - v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1" - integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1/events/integrationevents" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" + v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1" + integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/events/integrationevents" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" "github.com/mehdihadeli/go-mediatr" uuid "github.com/satori/go.uuid" @@ -46,14 +46,19 @@ var _ = Describe("Delete Product Feature", func() { _ = BeforeEach(func() { By("Seeding the required data") - integrationFixture.InitializeTest() + // call base SetupTest hook before running child hook + integrationFixture.SetupTest() + // child hook codes should be here id = integrationFixture.Items[0].ProductId }) _ = AfterEach(func() { By("Cleanup test data") - integrationFixture.DisposeTest() + // call base TearDownTest hook before running child hook + integrationFixture.TearDownTest() + + // child hook codes should be here }) _ = BeforeSuite(func() { @@ -87,25 +92,33 @@ var _ = Describe("Delete Product Feature", func() { Expect(err).ShouldNot(HaveOccurred()) }) - When("the DeleteProduct command is executed for existing product", func() { - BeforeEach(func() { - result, err = mediatr.Send[*v1.DeleteProduct, *mediatr.Unit]( - ctx, - command, - ) - }) - - It("Should not return an error", func() { - Expect(err).NotTo(HaveOccurred()) - }) - - It("Should delete the product from the database", func() { - deletedProduct, err := integrationFixture.ProductRepository.GetProductById(ctx, id) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(ContainSubstring("can't find the product with id"))) - Expect(deletedProduct).To(BeNil()) - }) - }) + When( + "the DeleteProduct command is executed for existing product", + func() { + BeforeEach(func() { + result, err = mediatr.Send[*v1.DeleteProduct, *mediatr.Unit]( + ctx, + command, + ) + }) + + It("Should not return an error", func() { + Expect(err).NotTo(HaveOccurred()) + }) + + It("Should delete the product from the database", func() { + deletedProduct, err := integrationFixture.CatalogsDBContext.FindProductByID( + ctx, + id, + ) + Expect(err).To(HaveOccurred()) + Expect( + err, + ).To(MatchError(ContainSubstring(fmt.Sprintf("product with id `%s` not found in the database", command.ProductID.String())))) + Expect(deletedProduct).To(BeNil()) + }) + }, + ) }) }) @@ -118,59 +131,76 @@ var _ = Describe("Delete Product Feature", func() { Expect(err).ShouldNot(HaveOccurred()) }) - When("the DeleteProduct command is executed for non-existing product", func() { - BeforeEach(func() { - result, err = mediatr.Send[*v1.DeleteProduct, *mediatr.Unit]( - ctx, - command, - ) - }) - - It("Should return an error", func() { - Expect(err).To(HaveOccurred()) - }) - - It("Should return a NotFound error", func() { - Expect(err).To(MatchError(ContainSubstring("product not found"))) - }) - - It("Should return a custom NotFound error", func() { - Expect(customErrors.IsApplicationError(err, http.StatusNotFound)).To(BeTrue()) - Expect(customErrors.IsNotFoundError(err)).To(BeTrue()) - }) - - It("Should not return a result", func() { - Expect(result).To(BeNil()) - }) - }) + When( + "the DeleteProduct command is executed for non-existing product", + func() { + BeforeEach(func() { + result, err = mediatr.Send[*v1.DeleteProduct, *mediatr.Unit]( + ctx, + command, + ) + }) + + It("Should return an error", func() { + Expect(err).To(HaveOccurred()) + }) + + It("Should return a NotFound error", func() { + Expect( + err, + ).To(MatchError(ContainSubstring(fmt.Sprintf("product with id `%s` not found in the database", command.ProductID.String())))) + }) + + It("Should return a custom NotFound error", func() { + Expect(customErrors.IsNotFoundError(err)).To(BeTrue()) + }) + + It("Should not return a result", func() { + Expect(result).To(BeNil()) + }) + }, + ) }) }) - Describe("Publishing ProductDeleted event when product deleted successfully", func() { - Context("Given product already exists in the system", func() { - BeforeEach(func() { - shouldPublish = messaging.ShouldProduced[*integrationEvents.ProductDeletedV1]( - ctx, - integrationFixture.Bus, - nil, - ) - command, err = v1.NewDeleteProduct(id) - Expect(err).ShouldNot(HaveOccurred()) - }) - - When("the DeleteProduct command is executed for existing product", func() { + Describe( + "Publishing ProductDeleted event when product deleted successfully", + func() { + Context("Given product already exists in the system", func() { BeforeEach(func() { - result, err = mediatr.Send[*v1.DeleteProduct, *mediatr.Unit]( + shouldPublish = messaging.ShouldProduced[*integrationEvents.ProductDeletedV1]( ctx, - command, + integrationFixture.Bus, + nil, ) + command, err = v1.NewDeleteProduct(id) + Expect(err).ShouldNot(HaveOccurred()) }) - It("Should publish ProductDeleted event to the broker", func() { - // ensuring message published to the rabbitmq broker - shouldPublish.Validate(ctx, "there is no published message", time.Second*30) - }) + When( + "the DeleteProduct command is executed for existing product", + func() { + BeforeEach(func() { + result, err = mediatr.Send[*v1.DeleteProduct, *mediatr.Unit]( + ctx, + command, + ) + }) + + It( + "Should publish ProductDeleted event to the broker", + func() { + // ensuring message published to the rabbitmq broker + shouldPublish.Validate( + ctx, + "there is no published message", + time.Second*30, + ) + }, + ) + }, + ) }) - }) - }) + }, + ) }) diff --git a/internal/services/catalog_write_service/test/integration/products/features/getting_product_by_id/v1/get_product_by_id_test.go b/internal/services/catalog_write_service/test/integration/products/features/getting_product_by_id/v1/get_product_by_id_test.go deleted file mode 100644 index cad38852..00000000 --- a/internal/services/catalog_write_service/test/integration/products/features/getting_product_by_id/v1/get_product_by_id_test.go +++ /dev/null @@ -1,143 +0,0 @@ -//go:build integration -// +build integration - -package v1 - -import ( - "context" - "net/http" - "testing" - "time" - - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - getProductByIdQuery "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1/dtos" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" - - "github.com/mehdihadeli/go-mediatr" - uuid "github.com/satori/go.uuid" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var integrationFixture *integration.IntegrationTestSharedFixture - -func TestGetProductById(t *testing.T) { - RegisterFailHandler(Fail) - integrationFixture = integration.NewIntegrationTestSharedFixture(t) - RunSpecs(t, "Get Product By ID Integration Tests") -} - -var _ = Describe("Get Product by ID Feature", func() { - var ( - ctx context.Context - id uuid.UUID - query *getProductByIdQuery.GetProductById - result *dtos.GetProductByIdResponseDto - err error - ) - - _ = BeforeEach(func() { - By("Seeding the required data") - integrationFixture.InitializeTest() - - id = integrationFixture.Items[0].ProductId - }) - - _ = AfterEach(func() { - By("Cleanup test data") - integrationFixture.DisposeTest() - }) - - _ = BeforeSuite(func() { - ctx = context.Background() - - // in test mode we set rabbitmq `AutoStart=false` in configuration in rabbitmqOptions, so we should run rabbitmq bus manually - err = integrationFixture.Bus.Start(context.Background()) - Expect(err).ShouldNot(HaveOccurred()) - - // wait for consumers ready to consume before publishing messages, preparation background workers takes a bit time (for preventing messages lost) - time.Sleep(1 * time.Second) - }) - - _ = AfterSuite(func() { - integrationFixture.Log.Info("TearDownSuite started") - err := integrationFixture.Bus.Stop() - Expect(err).ShouldNot(HaveOccurred()) - time.Sleep(1 * time.Second) - }) - - // "Scenario" step for testing returning an existing product with correct properties - Describe("Returning an existing product with valid Id from the database with correct properties", func() { - Context("Given products exists in the database", func() { - BeforeEach(func() { - query, err = getProductByIdQuery.NewGetProductById(id) - }) - - // "When" step - When("the GteProductById query is executed for existing product", func() { - BeforeEach(func() { - result, err = mediatr.Send[*getProductByIdQuery.GetProductById, *dtos.GetProductByIdResponseDto]( - ctx, - query, - ) - }) - - // "Then" step - It("Should not return an error", func() { - Expect(err).To(BeNil()) - }) - - It("Should return a non-nil result", func() { - Expect(result).NotTo(BeNil()) - }) - - It("Should return a product with the correct ID", func() { - Expect(result.Product).NotTo(BeNil()) - Expect(result.Product.ProductId).To(Equal(id)) - }) - }) - }) - }) - - // "Scenario" step for testing returning a NotFound error when record does not exist - Describe("Returning a NotFound error when product with specific id does not exist", func() { - Context("Given products does not exists in the database", func() { - BeforeEach(func() { - // Generate a random UUID that does not exist in the database - id = uuid.NewV4() - query, err = getProductByIdQuery.NewGetProductById(id) - Expect(err).To(BeNil()) - }) - - // "When" step - When("the GteProductById query is executed for non-existing product", func() { - BeforeEach(func() { - result, err = mediatr.Send[*getProductByIdQuery.GetProductById, *dtos.GetProductByIdResponseDto]( - ctx, - query, - ) - }) - - // "Then" step - It("Should return an error", func() { - Expect(err).To(HaveOccurred()) - }) - - It("Should return a NotFound error", func() { - Expect(err).To(MatchError(ContainSubstring("error in getting product with id"))) - }) - - It("Should return a custom NotFound error", func() { - Expect(customErrors.IsNotFoundError(err)).To(BeTrue()) - Expect(customErrors.IsApplicationError(err, http.StatusNotFound)).To(BeTrue()) - }) - - It("Should not return a result", func() { - Expect(result).To(BeNil()) - }) - }) - }) - }) -}) diff --git a/internal/services/catalog_write_service/test/integration/products/features/gettingproductbyid/v1/get_product_by_id_test.go b/internal/services/catalog_write_service/test/integration/products/features/gettingproductbyid/v1/get_product_by_id_test.go new file mode 100644 index 00000000..1d1cdbca --- /dev/null +++ b/internal/services/catalog_write_service/test/integration/products/features/gettingproductbyid/v1/get_product_by_id_test.go @@ -0,0 +1,166 @@ +//go:build integration +// +build integration + +package v1 + +import ( + "context" + "fmt" + "testing" + "time" + + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + getProductByIdQuery "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" + + "github.com/mehdihadeli/go-mediatr" + uuid "github.com/satori/go.uuid" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var integrationFixture *integration.IntegrationTestSharedFixture + +func TestGetProductById(t *testing.T) { + RegisterFailHandler(Fail) + integrationFixture = integration.NewIntegrationTestSharedFixture(t) + RunSpecs(t, "Get Product By ID Integration Tests") +} + +var _ = Describe("Get Product by ID Feature", func() { + var ( + ctx context.Context + id uuid.UUID + query *getProductByIdQuery.GetProductById + result *dtos.GetProductByIdResponseDto + err error + ) + + _ = BeforeEach(func() { + By("Seeding the required data") + // call base SetupTest hook before running child hook + integrationFixture.SetupTest() + + // child hook codes should be here + id = integrationFixture.Items[0].ProductId + }) + + _ = AfterEach(func() { + By("Cleanup test data") + // call base TearDownTest hook before running child hook + integrationFixture.TearDownTest() + + // child hook codes should be here + }) + + _ = BeforeSuite(func() { + ctx = context.Background() + + // in test mode we set rabbitmq `AutoStart=false` in configuration in rabbitmqOptions, so we should run rabbitmq bus manually + err = integrationFixture.Bus.Start(context.Background()) + Expect(err).ShouldNot(HaveOccurred()) + + // wait for consumers ready to consume before publishing messages, preparation background workers takes a bit time (for preventing messages lost) + time.Sleep(1 * time.Second) + }) + + _ = AfterSuite(func() { + integrationFixture.Log.Info("TearDownSuite started") + err := integrationFixture.Bus.Stop() + Expect(err).ShouldNot(HaveOccurred()) + time.Sleep(1 * time.Second) + }) + + // "Scenario" step for testing returning an existing product with correct properties + Describe( + "Returning an existing product with valid Id from the database with correct properties", + func() { + Context("Given products exists in the database", func() { + BeforeEach(func() { + query, err = getProductByIdQuery.NewGetProductById(id) + }) + + // "When" step + When( + "the GteProductById query is executed for existing product", + func() { + BeforeEach(func() { + result, err = mediatr.Send[*getProductByIdQuery.GetProductById, *dtos.GetProductByIdResponseDto]( + ctx, + query, + ) + }) + + // "Then" step + It("Should not return an error", func() { + Expect(err).To(BeNil()) + }) + + It("Should return a non-nil result", func() { + Expect(result).NotTo(BeNil()) + }) + + It( + "Should return a product with the correct ID", + func() { + Expect(result.Product).NotTo(BeNil()) + Expect(result.Product.ProductId).To(Equal(id)) + }, + ) + }, + ) + }) + }, + ) + + // "Scenario" step for testing returning a NotFound error when record does not exist + Describe( + "Returning a NotFound error when product with specific id does not exist", + func() { + Context("Given products does not exists in the database", func() { + BeforeEach(func() { + // Generate a random UUID that does not exist in the database + id = uuid.NewV4() + query, err = getProductByIdQuery.NewGetProductById(id) + Expect(err).To(BeNil()) + }) + + // "When" step + When( + "the GteProductById query is executed for non-existing product", + func() { + BeforeEach(func() { + result, err = mediatr.Send[*getProductByIdQuery.GetProductById, *dtos.GetProductByIdResponseDto]( + ctx, + query, + ) + }) + + // "Then" step + It("Should return an error", func() { + Expect(err).To(HaveOccurred()) + }) + + It("Should return a NotFound error", func() { + Expect( + err, + ).To(MatchError(ContainSubstring(fmt.Sprintf("product with id `%s` not found in the database", query.ProductID.String())))) + }) + + It("Should return a custom NotFound error", func() { + Expect( + customErrors.IsNotFoundError(err), + ).To(BeTrue()) + }) + + It("Should not return a result", func() { + Expect(result).To(BeNil()) + }) + }, + ) + }) + }, + ) +}) diff --git a/internal/services/catalog_write_service/test/integration/products/features/getting_products/v1/get_products_test.go b/internal/services/catalog_write_service/test/integration/products/features/gettingproducts/v1/get_products_test.go similarity index 77% rename from internal/services/catalog_write_service/test/integration/products/features/getting_products/v1/get_products_test.go rename to internal/services/catalog_write_service/test/integration/products/features/gettingproducts/v1/get_products_test.go index 9eff22de..34b00d42 100644 --- a/internal/services/catalog_write_service/test/integration/products/features/getting_products/v1/get_products_test.go +++ b/internal/services/catalog_write_service/test/integration/products/features/gettingproducts/v1/get_products_test.go @@ -9,9 +9,9 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - getProductsQueryV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/dtos" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" + gettingproductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" "github.com/mehdihadeli/go-mediatr" @@ -31,19 +31,25 @@ var _ = Describe("Get All Products Feature", func() { // Define variables to hold query and result data var ( ctx context.Context - query *getProductsQueryV1.GetProducts + query *gettingproductsv1.GetProducts queryResult *dtos.GetProductsResponseDto err error ) _ = BeforeEach(func() { By("Seeding the required data") - integrationFixture.InitializeTest() + // call base SetupTest hook before running child hook + integrationFixture.SetupTest() + + // child hook codes should be here }) _ = AfterEach(func() { By("Cleanup test data") - integrationFixture.DisposeTest() + // call base TearDownTest hook before running child hook + integrationFixture.TearDownTest() + + // child hook codes should be here }) _ = BeforeSuite(func() { @@ -69,7 +75,9 @@ var _ = Describe("Get All Products Feature", func() { Context("Given existing products in the database", func() { BeforeEach(func() { // Create a query to retrieve a list of products - query, err = queries.NewGetProducts(utils.NewListQuery(10, 1)) + query, err = gettingproductsv1.NewGetProducts( + utils.NewListQuery(10, 1), + ) Expect(err).To(BeNil()) }) @@ -78,7 +86,7 @@ var _ = Describe("Get All Products Feature", func() { "the GteProducts query is executed for existing products", func() { BeforeEach(func() { - queryResult, err = mediatr.Send[*queries.GetProducts, *dtos.GetProductsResponseDto]( + queryResult, err = mediatr.Send[*gettingproductsv1.GetProducts, *dtos.GetProductsResponseDto]( ctx, query, ) @@ -99,7 +107,7 @@ var _ = Describe("Get All Products Feature", func() { }) It("Should return the expected number of products", func() { - // Replace 'len(c.Items)' with the expected number of products + // Replace 'len(c.Products)' with the expected number of products Expect( len(queryResult.Products.Items), ).To(Equal(len(integrationFixture.Items))) diff --git a/internal/services/catalog_write_service/test/integration/products/features/updating_product/v1/update_product_test.go b/internal/services/catalog_write_service/test/integration/products/features/updatingproduct/v1/update_product_test.go similarity index 56% rename from internal/services/catalog_write_service/test/integration/products/features/updating_product/v1/update_product_test.go rename to internal/services/catalog_write_service/test/integration/products/features/updatingproduct/v1/update_product_test.go index d261a240..f97365c2 100644 --- a/internal/services/catalog_write_service/test/integration/products/features/updating_product/v1/update_product_test.go +++ b/internal/services/catalog_write_service/test/integration/products/features/updatingproduct/v1/update_product_test.go @@ -13,10 +13,10 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/hypothesis" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging" - v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1/events/integrationevents" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/integration" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" + v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/events/integrationevents" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" "github.com/mehdihadeli/go-mediatr" uuid "github.com/satori/go.uuid" @@ -37,7 +37,7 @@ var _ = Describe("Update Product Feature", func() { // Define variables to hold command and result data var ( ctx context.Context - existingProduct *models.Product + existingProduct *datamodel.ProductDataModel command *v1.UpdateProduct result *mediatr.Unit err error @@ -47,14 +47,14 @@ var _ = Describe("Update Product Feature", func() { _ = BeforeEach(func() { By("Seeding the required data") - integrationFixture.InitializeTest() + integrationFixture.SetupTest() existingProduct = integrationFixture.Items[0] }) _ = AfterEach(func() { By("Cleanup test data") - integrationFixture.DisposeTest() + integrationFixture.TearDownTest() }) _ = BeforeSuite(func() { @@ -91,7 +91,10 @@ var _ = Describe("Update Product Feature", func() { // "When" step When("the UpdateProduct command is executed", func() { BeforeEach(func() { - result, err = mediatr.Send[*v1.UpdateProduct, *mediatr.Unit](ctx, command) + result, err = mediatr.Send[*v1.UpdateProduct, *mediatr.Unit]( + ctx, + command, + ) }) // "Then" step @@ -104,17 +107,26 @@ var _ = Describe("Update Product Feature", func() { Expect(result).NotTo(BeNil()) }) - It("Should update the existing product in the database", func() { - updatedProduct, err := integrationFixture.ProductRepository.GetProductById( - ctx, - existingProduct.ProductId, - ) - Expect(err).To(BeNil()) - Expect(updatedProduct).NotTo(BeNil()) - Expect(updatedProduct.ProductId).To(Equal(existingProduct.ProductId)) - Expect(updatedProduct.Price).To(Equal(existingProduct.Price)) - Expect(updatedProduct.Name).NotTo(Equal(existingProduct.Name)) - }) + It( + "Should update the existing product in the database", + func() { + updatedProduct, err := integrationFixture.CatalogsDBContext.FindProductByID( + ctx, + existingProduct.ProductId, + ) + Expect(err).To(BeNil()) + Expect(updatedProduct).NotTo(BeNil()) + Expect( + updatedProduct.ProductId, + ).To(Equal(existingProduct.ProductId)) + Expect( + updatedProduct.Price, + ).To(Equal(existingProduct.Price)) + Expect( + updatedProduct.Name, + ).NotTo(Equal(existingProduct.Name)) + }, + ) }) }) }) @@ -135,61 +147,90 @@ var _ = Describe("Update Product Feature", func() { }) // "When" step - When("the UpdateProduct command executed for non-existing product", func() { - BeforeEach(func() { - result, err = mediatr.Send[*v1.UpdateProduct, *mediatr.Unit](ctx, command) - }) - - // "Then" step - It("Should return an error", func() { - Expect(err).To(HaveOccurred()) - }) - It("Should not return a result", func() { - Expect(result).To(BeNil()) - }) - - It("Should return a NotFound error", func() { - Expect(err).To(MatchError(ContainSubstring(fmt.Sprintf("product with id %s not found", id)))) - }) - - It("Should return a custom NotFound error", func() { - Expect(customErrors.IsNotFoundError(err)).To(BeTrue()) - Expect(customErrors.IsApplicationError(err, http.StatusNotFound)).To(BeTrue()) - }) - }) + When( + "the UpdateProduct command executed for non-existing product", + func() { + BeforeEach(func() { + result, err = mediatr.Send[*v1.UpdateProduct, *mediatr.Unit]( + ctx, + command, + ) + }) + + // "Then" step + It("Should return an error", func() { + Expect(err).To(HaveOccurred()) + }) + It("Should not return a result", func() { + Expect(result).To(BeNil()) + }) + + It("Should return a NotFound error", func() { + Expect( + err, + ).To(MatchError(ContainSubstring(fmt.Sprintf("product with id `%s` not found", id.String())))) + }) + + It("Should return a custom NotFound error", func() { + Expect(customErrors.IsNotFoundError(err)).To(BeTrue()) + Expect( + customErrors.IsApplicationError( + err, + http.StatusNotFound, + ), + ).To(BeTrue()) + }) + }, + ) }) }) // "Scenario" step for testing updating an existing product - Describe("Publishing ProductUpdated when product updated successfully", func() { - Context("Given product exists in the database", func() { - BeforeEach(func() { - command, err = v1.NewUpdateProduct( - existingProduct.ProductId, - "Updated Product Name", - existingProduct.Description, - existingProduct.Price, - ) - Expect(err).NotTo(HaveOccurred()) - - shouldPublish = messaging.ShouldProduced[*integrationevents.ProductUpdatedV1]( - ctx, - integrationFixture.Bus, - nil, - ) - }) - - // "When" step - When("the UpdateProduct command is executed for existing product", func() { + Describe( + "Publishing ProductUpdated when product updated successfully", + func() { + Context("Given product exists in the database", func() { BeforeEach(func() { - result, err = mediatr.Send[*v1.UpdateProduct, *mediatr.Unit](ctx, command) - }) + command, err = v1.NewUpdateProduct( + existingProduct.ProductId, + "Updated Product Name", + existingProduct.Description, + existingProduct.Price, + ) + Expect(err).NotTo(HaveOccurred()) - It("Should publish ProductUpdated event to the broker", func() { - // ensuring message published to the rabbitmq broker - shouldPublish.Validate(ctx, "there is no published message", time.Second*30) + shouldPublish = messaging.ShouldProduced[*integrationevents.ProductUpdatedV1]( + ctx, + integrationFixture.Bus, + nil, + ) }) + + // "When" step + When( + "the UpdateProduct command is executed for existing product", + func() { + BeforeEach(func() { + result, err = mediatr.Send[*v1.UpdateProduct, *mediatr.Unit]( + ctx, + command, + ) + }) + + It( + "Should publish ProductUpdated event to the broker", + func() { + // ensuring message published to the rabbitmq broker + shouldPublish.Validate( + ctx, + "there is no published message", + time.Second*30, + ) + }, + ) + }, + ) }) - }) - }) + }, + ) }) diff --git a/internal/services/catalog_write_service/test/unit/products/features/creating_product/v1/commands/create_product_handler_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/creating_product/v1/commands/create_product_handler_unit_test.go deleted file mode 100644 index 06a382be..00000000 --- a/internal/services/catalog_write_service/test/unit/products/features/creating_product/v1/commands/create_product_handler_unit_test.go +++ /dev/null @@ -1,180 +0,0 @@ -//go:build unit -// +build unit - -package commands - -import ( - "context" - "errors" - "net/http" - "testing" - "time" - - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - createProductCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/commands" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/mocks/testData" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" - - "github.com/brianvoe/gofakeit/v6" - uuid "github.com/satori/go.uuid" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/suite" -) - -type createProductHandlerUnitTests struct { - *unit_test.UnitTestSharedFixture -} - -func TestCreateProductHandlerUnit(t *testing.T) { - suite.Run( - t, - &createProductHandlerUnitTests{ - UnitTestSharedFixture: unit_test.NewUnitTestSharedFixture(t), - }, - ) -} - -func (c *createProductHandlerUnitTests) Test_Handle_Should_Create_New_Product_With_Valid_Data() { - ctx := context.Background() - id := uuid.NewV4() - - createProductHandler := createProductCommandV1.NewCreateProductHandler( - c.Log, - c.Uow, - c.Bus, - c.Tracer, - ) - - createProduct := &createProductCommandV1.CreateProduct{ - ProductID: id, - Name: gofakeit.Name(), - CreatedAt: time.Now(), - Description: gofakeit.EmojiDescription(), - Price: gofakeit.Price(100, 1000), - } - - product := testData.Products[0] - - c.ProductRepository.On("CreateProduct", mock.Anything, mock.Anything). - Once(). - Return(product, nil) - - dto, err := createProductHandler.Handle(ctx, createProduct) - c.Require().NoError(err) - - c.Uow.AssertNumberOfCalls(c.T(), "Do", 1) - c.ProductRepository.AssertNumberOfCalls(c.T(), "CreateProduct", 1) - c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 1) - c.Equal(dto.ProductID, id) -} - -func (c *createProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Duplicate_Item() { - ctx := context.Background() - id := uuid.NewV4() - - createProduct := &createProductCommandV1.CreateProduct{ - ProductID: id, - Name: gofakeit.Name(), - CreatedAt: time.Now(), - Description: gofakeit.EmojiDescription(), - Price: gofakeit.Price(100, 1000), - } - - c.ProductRepository.On("CreateProduct", mock.Anything, mock.Anything). - Once(). - Return(nil, errors.New("error duplicate product")) - - createProductHandler := createProductCommandV1.NewCreateProductHandler( - c.Log, - c.Uow, - c.Bus, - c.Tracer, - ) - - dto, err := createProductHandler.Handle(ctx, createProduct) - - c.Uow.AssertNumberOfCalls(c.T(), "Do", 1) - c.ProductRepository.AssertNumberOfCalls(c.T(), "CreateProduct", 1) - c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 0) - c.True(customErrors.IsApplicationError(err, http.StatusConflict)) - c.ErrorContains(err, "product already exists") - c.Nil(dto) -} - -func (c *createProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Error_In_Bus() { - ctx := context.Background() - id := uuid.NewV4() - - createProduct := &createProductCommandV1.CreateProduct{ - ProductID: id, - Name: gofakeit.Name(), - CreatedAt: time.Now(), - Description: gofakeit.EmojiDescription(), - Price: gofakeit.Price(100, 1000), - } - - product := testData.Products[0] - c.ProductRepository.On("CreateProduct", mock.Anything, mock.Anything). - Once(). - Return(product, nil) - - // override called mock - // https://github.com/stretchr/testify/issues/558 - c.Bus.Mock.ExpectedCalls = nil - c.Bus.On("PublishMessage", mock.Anything, mock.Anything, mock.Anything). - Once(). - Return(errors.New("error in the publish message")) - - createProductHandler := createProductCommandV1.NewCreateProductHandler( - c.Log, - c.Uow, - c.Bus, - c.Tracer, - ) - - dto, err := createProductHandler.Handle(ctx, createProduct) - - c.Uow.AssertNumberOfCalls(c.T(), "Do", 1) - c.ProductRepository.AssertNumberOfCalls(c.T(), "CreateProduct", 1) - c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 1) - c.ErrorContains(err, "error in the publish message") - c.ErrorContains(err, "error in publishing ProductCreated integration_events event") - c.Nil(dto) -} - -func (c *createProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Error_In_Mapping() { - ctx := context.Background() - id := uuid.NewV4() - - createProduct := &createProductCommandV1.CreateProduct{ - ProductID: id, - Name: gofakeit.Name(), - CreatedAt: time.Now(), - Description: gofakeit.EmojiDescription(), - Price: gofakeit.Price(100, 1000), - } - - product := testData.Products[0] - c.ProductRepository.On("CreateProduct", mock.Anything, mock.Anything). - Once(). - Return(product, nil) - - mapper.ClearMappings() - - createProductHandler := createProductCommandV1.NewCreateProductHandler( - c.Log, - c.Uow, - c.Bus, - c.Tracer, - ) - - dto, err := createProductHandler.Handle(ctx, createProduct) - - c.Uow.AssertNumberOfCalls(c.T(), "Do", 1) - c.ProductRepository.AssertNumberOfCalls(c.T(), "CreateProduct", 1) - c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 0) - c.ErrorContains(err, "error in the mapping ProductDto") - c.True(customErrors.IsApplicationError(err, http.StatusInternalServerError)) - c.Nil(dto) -} diff --git a/internal/services/catalog_write_service/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go new file mode 100644 index 00000000..9daa5f84 --- /dev/null +++ b/internal/services/catalog_write_service/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go @@ -0,0 +1,164 @@ +//go:build unit +// +build unit + +package v1 + +import ( + "testing" + "time" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" + creatingproductv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1" + creatingproductdtosv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" + + "emperror.dev/errors" + "github.com/brianvoe/gofakeit/v6" + uuid "github.com/satori/go.uuid" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/suite" +) + +type createProductHandlerUnitTests struct { + *unittest.UnitTestSharedFixture + handler cqrs.RequestHandlerWithRegisterer[*creatingproductv1.CreateProduct, *creatingproductdtosv1.CreateProductResponseDto] +} + +func TestCreateProductHandlerUnit(t *testing.T) { + suite.Run(t, &createProductHandlerUnitTests{ + UnitTestSharedFixture: unittest.NewUnitTestSharedFixture(t), + }, + ) +} + +func (c *createProductHandlerUnitTests) SetupTest() { + // call base SetupTest hook before running child hook + c.UnitTestSharedFixture.SetupTest() + c.handler = creatingproductv1.NewCreateProductHandler( + fxparams.ProductHandlerParams{ + CatalogsDBContext: c.CatalogDBContext, + Tracer: c.Tracer, + RabbitmqProducer: c.Bus, + Log: c.Log, + }, + ) +} + +func (c *createProductHandlerUnitTests) TearDownTest() { + // call base TearDownTest hook before running child hook + c.UnitTestSharedFixture.TearDownTest() +} + +func (c *createProductHandlerUnitTests) Test_Handle_Should_Create_New_Product_With_Valid_Data() { + id := uuid.NewV4() + + createProduct := &creatingproductv1.CreateProduct{ + ProductID: id, + Name: gofakeit.Name(), + CreatedAt: time.Now(), + Description: gofakeit.EmojiDescription(), + Price: gofakeit.Price(100, 1000), + } + + c.BeginTx() + + _, err := c.handler.Handle(c.Ctx, createProduct) + c.Require().NoError(err) + + c.CommitTx() + + c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 1) + + res, err := c.CatalogDBContext.FindProductByID(c.Ctx, id) + c.Require().NoError(err) + + c.Assert().Equal(res.ProductId, id) +} + +func (c *createProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Duplicate_Item() { + id := uuid.NewV4() + + createProduct := &creatingproductv1.CreateProduct{ + ProductID: id, + Name: gofakeit.Name(), + CreatedAt: time.Now(), + Description: gofakeit.EmojiDescription(), + Price: gofakeit.Price(100, 1000), + } + + c.BeginTx() + dto, err := c.handler.Handle(c.Ctx, createProduct) + c.Require().NoError(err) + c.Require().NotNil(dto) + c.CommitTx() + + c.BeginTx() + dto, err = c.handler.Handle(c.Ctx, createProduct) + c.CommitTx() + + c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 1) + c.True(customErrors.IsConflictError(err)) + c.ErrorContains(err, "product already exists") + c.Nil(dto) +} + +func (c *createProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Error_In_Bus() { + id := uuid.NewV4() + + createProduct := &creatingproductv1.CreateProduct{ + ProductID: id, + Name: gofakeit.Name(), + CreatedAt: time.Now(), + Description: gofakeit.EmojiDescription(), + Price: gofakeit.Price(100, 1000), + } + + // override called mock + // https://github.com/stretchr/testify/issues/558 + c.Bus.Mock.ExpectedCalls = nil + c.Bus.On("PublishMessage", mock.Anything, mock.Anything, mock.Anything). + Once(). + Return(errors.New("error in the publish message")) + + c.BeginTx() + + dto, err := c.handler.Handle(c.Ctx, createProduct) + + c.CommitTx() + + c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 1) + c.ErrorContains(err, "error in the publish message") + c.ErrorContains( + err, + "error in publishing ProductCreated integration_events event", + ) + c.Nil(dto) +} + +func (c *createProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Error_In_Mapping() { + id := uuid.NewV4() + + createProduct := &creatingproductv1.CreateProduct{ + ProductID: id, + Name: gofakeit.Name(), + CreatedAt: time.Now(), + Description: gofakeit.EmojiDescription(), + Price: gofakeit.Price(100, 1000), + } + + mapper.ClearMappings() + + c.BeginTx() + + dto, err := c.handler.Handle(c.Ctx, createProduct) + + c.CommitTx() + + c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 0) + c.ErrorContains(err, "error in the mapping") + c.True(customErrors.IsInternalServerError(err)) + c.Nil(dto) +} diff --git a/internal/services/catalog_write_service/test/unit/products/features/creating_product/v1/commands/create_product_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/creatingproduct/v1/create_product_unit_test.go similarity index 72% rename from internal/services/catalog_write_service/test/unit/products/features/creating_product/v1/commands/create_product_unit_test.go rename to internal/services/catalog_write_service/test/unit/products/features/creatingproduct/v1/create_product_unit_test.go index e409c6f7..08170be0 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/creating_product/v1/commands/create_product_unit_test.go +++ b/internal/services/catalog_write_service/test/unit/products/features/creatingproduct/v1/create_product_unit_test.go @@ -1,26 +1,28 @@ //go:build unit // +build unit -package commands +package v1 import ( "testing" - createProductCommand "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/commands" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" + createProductCommand "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" "github.com/brianvoe/gofakeit/v6" "github.com/stretchr/testify/suite" ) type createProductUnitTests struct { - *unit_test.UnitTestSharedFixture + *unittest.UnitTestSharedFixture } func TestCreateProductUnit(t *testing.T) { suite.Run( t, - &createProductUnitTests{UnitTestSharedFixture: unit_test.NewUnitTestSharedFixture(t)}, + &createProductUnitTests{ + UnitTestSharedFixture: unittest.NewUnitTestSharedFixture(t), + }, ) } @@ -29,7 +31,11 @@ func (c *createProductUnitTests) Test_New_Create_Product_Should_Return_No_Error_ description := gofakeit.EmojiDescription() price := gofakeit.Price(150, 6000) - updateProduct, err := createProductCommand.NewCreateProduct(name, description, price) + updateProduct, err := createProductCommand.NewCreateProduct( + name, + description, + price, + ) c.Assert().NotNil(updateProduct) c.Assert().Equal(name, updateProduct.Name) @@ -50,14 +56,22 @@ func (c *createProductUnitTests) Test_New_Create_Product_Should_Return_Error_For } func (c *createProductUnitTests) Test_New_Create_Product_Should_Return_Error_For_Empty_Name() { - command, err := createProductCommand.NewCreateProduct("", gofakeit.EmojiDescription(), 120) + command, err := createProductCommand.NewCreateProduct( + "", + gofakeit.EmojiDescription(), + 120, + ) c.Require().Error(err) c.Assert().Nil(command) } func (c *createProductUnitTests) Test_New_Create_Product_Should_Return_Error_For_Empty_Description() { - command, err := createProductCommand.NewCreateProduct(gofakeit.Name(), "", 120) + command, err := createProductCommand.NewCreateProduct( + gofakeit.Name(), + "", + 120, + ) c.Require().Error(err) c.Assert().Nil(command) diff --git a/internal/services/catalog_write_service/test/unit/products/features/deleting_product/v1/commands/delete_product_handler_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/deleting_product/v1/commands/delete_product_handler_unit_test.go deleted file mode 100644 index 3fed6f27..00000000 --- a/internal/services/catalog_write_service/test/unit/products/features/deleting_product/v1/commands/delete_product_handler_unit_test.go +++ /dev/null @@ -1,110 +0,0 @@ -//go:build unit -// +build unit - -package commands - -import ( - "context" - "net/http" - "testing" - - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" - - "emperror.dev/errors" - uuid "github.com/satori/go.uuid" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/suite" -) - -type deleteProductHandlerUnitTests struct { - *unit_test.UnitTestSharedFixture -} - -func TestDeleteProductHandlerUnit(t *testing.T) { - suite.Run( - t, - &deleteProductHandlerUnitTests{ - UnitTestSharedFixture: unit_test.NewUnitTestSharedFixture(t), - }, - ) -} - -func (c *deleteProductHandlerUnitTests) Test_Handle_Should_Delete_Product_With_Valid_Id() { - ctx := context.Background() - id := c.Items[0].ProductId - - deleteProduct := &v1.DeleteProduct{ - ProductID: id, - } - - c.ProductRepository.On("DeleteProductByID", mock.Anything, id). - Once(). - Return(nil) - - deleteProductHandler := v1.NewDeleteProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) - - _, err := deleteProductHandler.Handle(ctx, deleteProduct) - c.Require().NoError(err) - - c.Uow.AssertNumberOfCalls(c.T(), "Do", 1) - c.ProductRepository.AssertNumberOfCalls(c.T(), "DeleteProductByID", 1) - c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 1) -} - -func (c *deleteProductHandlerUnitTests) Test_Handle_Should_Return_NotFound_Error_When_Id_Is_Invalid() { - ctx := context.Background() - id := uuid.NewV4() - - deleteProduct := &v1.DeleteProduct{ - ProductID: id, - } - - c.ProductRepository.On("DeleteProductByID", mock.Anything, id). - Once(). - Return(customErrors.NewNotFoundError("error finding product")) - - deleteProductHandler := v1.NewDeleteProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) - - res, err := deleteProductHandler.Handle(ctx, deleteProduct) - c.Require().Error(err) - c.True(customErrors.IsNotFoundError(err)) - c.True(customErrors.IsApplicationError(err, http.StatusNotFound)) - c.NotNil(res) - - c.Uow.AssertNumberOfCalls(c.T(), "Do", 1) - c.ProductRepository.AssertNumberOfCalls(c.T(), "DeleteProductByID", 1) - c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 0) -} - -func (c *deleteProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Error_In_Bus() { - ctx := context.Background() - id := c.Items[0].ProductId - - deleteProduct := &v1.DeleteProduct{ - ProductID: id, - } - - c.ProductRepository.On("DeleteProductByID", mock.Anything, id). - Once(). - Return(nil) - - // override called mock - // https://github.com/stretchr/testify/issues/558 - c.Bus.Mock.ExpectedCalls = nil - c.Bus.On("PublishMessage", mock.Anything, mock.Anything, mock.Anything). - Once(). - Return(errors.New("error in the publish message")) - - deleteProductHandler := v1.NewDeleteProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) - dto, err := deleteProductHandler.Handle(ctx, deleteProduct) - - c.NotNil(dto) - - c.Uow.AssertNumberOfCalls(c.T(), "Do", 1) - c.ProductRepository.AssertNumberOfCalls(c.T(), "DeleteProductByID", 1) - c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 1) - c.True(customErrors.IsApplicationError(err, http.StatusInternalServerError)) - c.ErrorContains(err, "error in publishing 'ProductDeleted' message") -} diff --git a/internal/services/catalog_write_service/test/unit/products/features/deletingproduct/v1/delete_product_handler_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/deletingproduct/v1/delete_product_handler_unit_test.go new file mode 100644 index 00000000..7a551929 --- /dev/null +++ b/internal/services/catalog_write_service/test/unit/products/features/deletingproduct/v1/delete_product_handler_unit_test.go @@ -0,0 +1,117 @@ +//go:build unit +// +build unit + +package v1 + +import ( + "net/http" + "testing" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" + deletingproductv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" + + "emperror.dev/errors" + "github.com/mehdihadeli/go-mediatr" + uuid "github.com/satori/go.uuid" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/suite" +) + +type deleteProductHandlerUnitTests struct { + *unittest.UnitTestSharedFixture + handler cqrs.RequestHandlerWithRegisterer[*deletingproductv1.DeleteProduct, *mediatr.Unit] +} + +func TestDeleteProductHandlerUnit(t *testing.T) { + suite.Run( + t, + &deleteProductHandlerUnitTests{ + UnitTestSharedFixture: unittest.NewUnitTestSharedFixture(t), + }, + ) +} + +func (c *deleteProductHandlerUnitTests) SetupTest() { + // call base SetupTest hook before running child hook + c.UnitTestSharedFixture.SetupTest() + c.handler = deletingproductv1.NewDeleteProductHandler( + fxparams.ProductHandlerParams{ + Log: c.Log, + CatalogsDBContext: c.CatalogDBContext, + RabbitmqProducer: c.Bus, + Tracer: c.Tracer, + }, + ) +} + +func (c *deleteProductHandlerUnitTests) TearDownTest() { + // call base TearDownTest hook before running child hook + c.UnitTestSharedFixture.TearDownTest() +} + +func (c *deleteProductHandlerUnitTests) Test_Handle_Should_Delete_Product_With_Valid_Id() { + id := c.Products[0].ProductId + + deleteProduct := &deletingproductv1.DeleteProduct{ + ProductID: id, + } + + c.BeginTx() + _, err := c.handler.Handle(c.Ctx, deleteProduct) + c.CommitTx() + + c.Require().NoError(err) + + p, err := c.CatalogDBContext.FindProductByID(c.Ctx, id) + + c.Require().Nil(p) + c.Require().Error(err) + + c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 1) +} + +func (c *deleteProductHandlerUnitTests) Test_Handle_Should_Return_NotFound_Error_When_Id_Is_Invalid() { + id := uuid.NewV4() + + deleteProduct := &deletingproductv1.DeleteProduct{ + ProductID: id, + } + + c.BeginTx() + res, err := c.handler.Handle(c.Ctx, deleteProduct) + c.CommitTx() + + c.Require().Error(err) + c.True(customErrors.IsNotFoundError(err)) + c.Nil(res) + + c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 0) +} + +func (c *deleteProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Error_In_Bus() { + id := c.Products[0].ProductId + + deleteProduct := &deletingproductv1.DeleteProduct{ + ProductID: id, + } + + // override called mock + // https://github.com/stretchr/testify/issues/558 + c.Bus.Mock.ExpectedCalls = nil + c.Bus.On("PublishMessage", mock.Anything, mock.Anything, mock.Anything). + Once(). + Return(errors.New("error in the publish message")) + + c.BeginTx() + dto, err := c.handler.Handle(c.Ctx, deleteProduct) + c.CommitTx() + + c.Nil(dto) + + c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 1) + c.True(customErrors.IsApplicationError(err, http.StatusInternalServerError)) + c.ErrorContains(err, "error in publishing 'ProductDeleted' message") +} diff --git a/internal/services/catalog_write_service/test/unit/products/features/deleting_product/v1/commands/delete_product_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/deletingproduct/v1/delete_product_unit_test.go similarity index 80% rename from internal/services/catalog_write_service/test/unit/products/features/deleting_product/v1/commands/delete_product_unit_test.go rename to internal/services/catalog_write_service/test/unit/products/features/deletingproduct/v1/delete_product_unit_test.go index ceb292f9..5ed6e23e 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/deleting_product/v1/commands/delete_product_unit_test.go +++ b/internal/services/catalog_write_service/test/unit/products/features/deletingproduct/v1/delete_product_unit_test.go @@ -1,26 +1,26 @@ //go:build unit // +build unit -package commands +package v1 import ( "testing" - v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deleting_product/v1" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" + v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" uuid "github.com/satori/go.uuid" "github.com/stretchr/testify/suite" ) type deleteProductUnitTests struct { - *unit_test.UnitTestSharedFixture + *unittest.UnitTestSharedFixture } func TestDeleteProductByIdUnit(t *testing.T) { suite.Run( t, - &deleteProductUnitTests{UnitTestSharedFixture: unit_test.NewUnitTestSharedFixture(t)}, + &deleteProductUnitTests{UnitTestSharedFixture: unittest.NewUnitTestSharedFixture(t)}, ) } diff --git a/internal/services/catalog_write_service/test/unit/products/features/getting_product_by_id/v1/queries/get_product_by_id_handler_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/getting_product_by_id/v1/queries/get_product_by_id_handler_unit_test.go deleted file mode 100644 index 74bc3044..00000000 --- a/internal/services/catalog_write_service/test/unit/products/features/getting_product_by_id/v1/queries/get_product_by_id_handler_unit_test.go +++ /dev/null @@ -1,209 +0,0 @@ -//go:build unit -// +build unit - -package queries - -import ( - "context" - "fmt" - "net/http" - "testing" - - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" - - uuid "github.com/satori/go.uuid" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/suite" -) - -type getProductByIdHandlerTest struct { - *unit_test.UnitTestSharedFixture -} - -func TestGetProductByIdHandlerUnit(t *testing.T) { - suite.Run( - t, - &getProductByIdHandlerTest{UnitTestSharedFixture: unit_test.NewUnitTestSharedFixture(t)}, - ) -} - -func (c *getProductByIdHandlerTest) Test_Get_Product_By_Id() { - product := c.Items[0] - id := uuid.NewV4() - testCases := []struct { - Name string - id uuid.UUID - HandlerError error - ProductRepositoryNumberOfCall int - ExpectedName string - ExpectedId uuid.UUID - RepositoryReturnProduct *models.Product - RepositoryReturnError error - fn func() - }{ - { - Name: "Handle_Should_Get_Product_Successfully", - id: product.ProductId, - HandlerError: nil, - ProductRepositoryNumberOfCall: 1, - ExpectedId: product.ProductId, - ExpectedName: product.Name, - RepositoryReturnProduct: product, - RepositoryReturnError: nil, - }, - { - Name: "Handle_Should_Return_NotFound_Error_For_NotFound_Item", - id: id, - HandlerError: customErrors.NewApplicationErrorWithCode( - fmt.Sprintf("error in getting product with id %s in the repository", id.String()), - http.StatusNotFound, - ), - ProductRepositoryNumberOfCall: 1, - ExpectedId: *new(uuid.UUID), - ExpectedName: "", - RepositoryReturnProduct: nil, - RepositoryReturnError: customErrors.NewNotFoundError("product not found"), - }, - { - Name: "Handle_Should_Return_Error_For_Error_In_Mapping", - id: product.ProductId, - HandlerError: customErrors.NewApplicationErrorWithCode( - "error in the mapping product", - http.StatusInternalServerError, - ), - ProductRepositoryNumberOfCall: 1, - ExpectedId: *new(uuid.UUID), - ExpectedName: "", - RepositoryReturnProduct: product, - RepositoryReturnError: nil, - fn: func() { - mapper.ClearMappings() - }, - }, - } - - ctx := context.Background() - for _, testCase := range testCases { - c.Run(testCase.Name, func() { - // arrange - // create new mocks or clear mocks before executing - c.CleanupMocks() - - getProductByIdHandler := v1.NewGetProductByIDHandler( - c.Log, - c.ProductRepository, - c.Tracer, - ) - - c.ProductRepository.On("GetProductById", mock.Anything, testCase.id). - Once(). - Return(testCase.RepositoryReturnProduct, testCase.RepositoryReturnError) - - if testCase.fn != nil { - testCase.fn() - } - - query, err := v1.NewGetProductById(testCase.id) - c.Require().NoError(err) - - // act - dto, err := getProductByIdHandler.Handle(ctx, query) - - // assert - c.ProductRepository.AssertNumberOfCalls( - c.T(), - "GetProductById", - testCase.ProductRepositoryNumberOfCall, - ) - if testCase.HandlerError == nil { - // success path with a valid dto - c.Require().NoError(err) - c.NotNil(dto.Product) - c.Equal(testCase.ExpectedId, dto.Product.ProductId) - c.Equal(testCase.ExpectedName, dto.Product.Name) - } else { - // handler error path - c.Nil(dto) - c.ErrorContains(err, testCase.HandlerError.Error()) - if customErrors.IsApplicationError(testCase.HandlerError, http.StatusNotFound) { - // not found error - c.True(customErrors.IsNotFoundError(err)) - c.True(customErrors.IsApplicationError(err, http.StatusNotFound)) - c.ErrorContains(err, testCase.HandlerError.Error()) - } else { - // mapping error - c.ErrorContains(err, testCase.HandlerError.Error()) - c.True(customErrors.IsApplicationError(err, http.StatusInternalServerError)) - } - } - }) - } - - //c.Register("Handle_Should_Get_Product_Successfully", func() { - // // create new mocks or clear mocks before executing - // c.UnitTestMockFixture = unit_test.NewUnitTestMockFixture(c.T()) - // c.getProductByIdHandler = NewGetProductByIdHandler(c.Log, c.Cfg, c.ProductRepository) - // - // c.ProductRepository.On("GetProductById", mock.Anything, product.ProductId). - // Once(). - // Return(product, nil) - // - // query := NewGetProductById(product.ProductId) - // - // dto, err := c.getProductByIdHandler.Handle(c.Ctx, query) - // c.Require().NoError(err) - // - // c.ProductRepository.AssertNumberOfCalls(c.T(), "GetProductById", 1) - // c.Equal(product.ProductId, dto.Product.ProductId) - // c.Equal(product.Name, dto.Product.Name) - //}) - // - //c.Register("Handle_Should_Return_NotFound_Error_For_NotFound_Item", func() { - // // create new mocks or clear mocks before executing - // c.UnitTestMockFixture = unit_test.NewUnitTestMockFixture(c.T()) - // c.getProductByIdHandler = NewGetProductByIdHandler(c.Log, c.Cfg, c.ProductRepository) - // - // c.ProductRepository.On("GetProductById", mock.Anything, id). - // Once(). - // Return(nil, customErrors.NewNotFoundError("product not found")) - // - // query := NewGetProductById(id) - // - // dto, err := c.getProductByIdHandler.Handle(c.Ctx, query) - // - // c.Require().Error(err) - // c.True(customErrors.IsApplicationError(err, http.StatusNotFound)) - // c.True(customErrors.IsNotFoundError(err)) - // c.ErrorContains(err, fmt.Sprintf("error in getting product with id %s in the repository", id.String())) - // c.Nil(dto) - // - // c.ProductRepository.AssertNumberOfCalls(c.T(), "GetProductById", 1) - //}) - // - //c.Register("Handle_Should_Return_Error_For_Error_In_Mapping", func() { - // // create new mocks or clear mocks before executing - // c.UnitTestMockFixture = unit_test.NewUnitTestMockFixture(c.T()) - // c.getProductByIdHandler = NewGetProductByIdHandler(c.Log, c.Cfg, c.ProductRepository) - // - // product := testData.Products[0] - // c.ProductRepository.On("GetProductById", mock.Anything, product.ProductId). - // Once(). - // Return(product, nil) - // - // mapper.ClearMappings() - // - // query := NewGetProductById(product.ProductId) - // - // dto, err := c.getProductByIdHandler.Handle(c.Ctx, query) - // - // c.ProductRepository.AssertNumberOfCalls(c.T(), "GetProductById", 1) - // c.Nil(dto) - // c.Require().Error(err) - // c.True(customErrors.IsApplicationError(err, http.StatusInternalServerError)) - // c.ErrorContains(err, "error in the mapping product") - //}) -} diff --git a/internal/services/catalog_write_service/test/unit/products/features/getting_products/v1/queries/get_products_handler_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/getting_products/v1/queries/get_products_handler_unit_test.go deleted file mode 100644 index 43ec49b9..00000000 --- a/internal/services/catalog_write_service/test/unit/products/features/getting_products/v1/queries/get_products_handler_unit_test.go +++ /dev/null @@ -1,96 +0,0 @@ -//go:build unit -// +build unit - -package queries - -import ( - "context" - "net/http" - "testing" - - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - getting_products2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/mocks/testData" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" - - "emperror.dev/errors" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/suite" -) - -type getProductsHandlerUnitTests struct { - *unit_test.UnitTestSharedFixture -} - -func TestGetProductsUnit(t *testing.T) { - suite.Run( - t, - &getProductsHandlerUnitTests{UnitTestSharedFixture: unit_test.NewUnitTestSharedFixture(t)}, - ) -} - -func (c *getProductsHandlerUnitTests) Test_Handle_Should_Return_Products_Successfully() { - ctx := context.Background() - - query, err := getting_products2.NewGetProducts(utils.NewListQuery(10, 1)) - c.Require().NoError(err) - - items := utils.NewListResult[*models.Product]( - testData.Products, - 10, - 1, - int64(len(testData.Products)), - ) - c.ProductRepository.On("GetAllProducts", mock.Anything, mock.Anything). - Once(). - Return(items, nil) - - getProductsHandler := getting_products2.NewGetProductsHandler(c.Log, c.ProductRepository, c.Tracer) - - res, err := getProductsHandler.Handle(ctx, query) - c.Require().NoError(err) - c.NotNil(res) - c.NotEmpty(res.Products) - c.Equal(len(testData.Products), len(res.Products.Items)) - c.ProductRepository.AssertNumberOfCalls(c.T(), "GetAllProducts", 1) -} - -func (c *getProductsHandlerUnitTests) Test_Handle_Should_Return_Error_For_Error_In_Fetching_Data_From_Repository() { - ctx := context.Background() - - query, err := queries.NewGetProducts(utils.NewListQuery(10, 1)) - c.Require().NoError(err) - - c.ProductRepository.On("GetAllProducts", mock.Anything, mock.Anything). - Once(). - Return(nil, errors.New("error in fetching products from repository")) - - getProductsHandler := queries.NewGetProductsHandler(c.Log, c.ProductRepository, c.Tracer) - - res, err := getProductsHandler.Handle(ctx, query) - c.Require().Error(err) - c.True(customErrors.IsApplicationError(err, http.StatusInternalServerError)) - c.Nil(res) - c.ProductRepository.AssertNumberOfCalls(c.T(), "GetAllProducts", 1) -} - -func (c *getProductsHandlerUnitTests) Test_Handle_Should_Return_Error_For_Mapping_List_Result() { - ctx := context.Background() - - query, err := queries.NewGetProducts(utils.NewListQuery(10, 1)) - c.Require().NoError(err) - - c.ProductRepository.On("GetAllProducts", mock.Anything, mock.Anything). - Once(). - Return(nil, nil) - - getProductsHandler := queries.NewGetProductsHandler(c.Log, c.ProductRepository, c.Tracer) - - res, err := getProductsHandler.Handle(ctx, query) - c.Require().Error(err) - c.True(customErrors.IsApplicationError(err, http.StatusInternalServerError)) - c.Nil(res) - c.ProductRepository.AssertNumberOfCalls(c.T(), "GetAllProducts", 1) -} diff --git a/internal/services/catalog_write_service/test/unit/products/features/getting_product_by_id/v1/queries/get_product_by_Id_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/gettingproductbyid/v1/get_product_by_Id_unit_test.go similarity index 79% rename from internal/services/catalog_write_service/test/unit/products/features/getting_product_by_id/v1/queries/get_product_by_Id_unit_test.go rename to internal/services/catalog_write_service/test/unit/products/features/gettingproductbyid/v1/get_product_by_Id_unit_test.go index feca8ee2..e1f146ef 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/getting_product_by_id/v1/queries/get_product_by_Id_unit_test.go +++ b/internal/services/catalog_write_service/test/unit/products/features/gettingproductbyid/v1/get_product_by_Id_unit_test.go @@ -1,26 +1,26 @@ //go:build unit // +build unit -package queries +package v1 import ( "testing" - getProductByIdQuery "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_product_by_id/v1" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" + getProductByIdQuery "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" uuid "github.com/satori/go.uuid" "github.com/stretchr/testify/suite" ) type getProductByIdUnitTests struct { - *unit_test.UnitTestSharedFixture + *unittest.UnitTestSharedFixture } func TestGetProductByIdUnit(t *testing.T) { suite.Run( t, - &getProductByIdUnitTests{UnitTestSharedFixture: unit_test.NewUnitTestSharedFixture(t)}, + &getProductByIdUnitTests{UnitTestSharedFixture: unittest.NewUnitTestSharedFixture(t)}, ) } diff --git a/internal/services/catalog_write_service/test/unit/products/features/gettingproductbyid/v1/get_product_by_id_handler_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/gettingproductbyid/v1/get_product_by_id_handler_unit_test.go new file mode 100644 index 00000000..7daf7d12 --- /dev/null +++ b/internal/services/catalog_write_service/test/unit/products/features/gettingproductbyid/v1/get_product_by_id_handler_unit_test.go @@ -0,0 +1,97 @@ +//go:build unit +// +build unit + +package v1 + +import ( + "fmt" + "testing" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" + gettingproductbyidv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" + + uuid "github.com/satori/go.uuid" + "github.com/stretchr/testify/suite" +) + +type getProductByIdHandlerTest struct { + *unittest.UnitTestSharedFixture + handler cqrs.RequestHandlerWithRegisterer[*gettingproductbyidv1.GetProductById, *dtos.GetProductByIdResponseDto] +} + +func TestGetProductByIdHandlerUnit(t *testing.T) { + suite.Run(t, &getProductByIdHandlerTest{ + UnitTestSharedFixture: unittest.NewUnitTestSharedFixture(t), + }) +} + +func (c *getProductByIdHandlerTest) SetupTest() { + // call base SetupTest hook before running child hook + c.UnitTestSharedFixture.SetupTest() + c.handler = gettingproductbyidv1.NewGetProductByIDHandler( + fxparams.ProductHandlerParams{ + CatalogsDBContext: c.CatalogDBContext, + Tracer: c.Tracer, + RabbitmqProducer: c.Bus, + Log: c.Log, + }) +} + +func (c *getProductByIdHandlerTest) TearDownTest() { + // call base TearDownTest hook before running child hook + c.UnitTestSharedFixture.TearDownTest() +} + +func (c *getProductByIdHandlerTest) Test_Handle_Should_Return_Correct_Product_By_ID() { + product := c.Products[0] + + query, err := gettingproductbyidv1.NewGetProductById(product.ProductId) + c.Require().NoError(err) + + dto, err := c.handler.Handle(c.Ctx, query) + c.Require().NoError(err) + c.Assert().NotNil(dto) + c.Assert().NotNil(dto.Product) + c.Assert().Equal(dto.Product.ProductId, product.ProductId) + c.Assert().Equal(dto.Product.Name, product.Name) +} + +func (c *getProductByIdHandlerTest) Test_Handle_Should_Return_NotFound_Error_For_NotFound_Item() { + id := uuid.NewV4() + + query, err := gettingproductbyidv1.NewGetProductById(id) + c.Require().NoError(err) + + dto, err := c.handler.Handle(c.Ctx, query) + c.Require().Error(err) + c.True(customErrors.IsNotFoundError(err)) + c.ErrorContains( + err, + fmt.Sprintf( + "product with id `%s` not found in the database", + id.String(), + ), + ) + c.Nil(dto) +} + +func (c *getProductByIdHandlerTest) Test_Handle_Should_Return_Error_For_Error_In_Mapping() { + mapper.ClearMappings() + + product := c.Products[0] + + query, err := gettingproductbyidv1.NewGetProductById(product.ProductId) + c.Require().NoError(err) + + dto, err := c.handler.Handle(c.Ctx, query) + + c.Nil(dto) + c.Require().Error(err) + c.True(customErrors.IsInternalServerError(err)) + c.ErrorContains(err, "error in the mapping Product") +} diff --git a/internal/services/catalog_write_service/test/unit/products/features/gettingproducts/v1/get_products_handler_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/gettingproducts/v1/get_products_handler_unit_test.go new file mode 100644 index 00000000..74a3b12a --- /dev/null +++ b/internal/services/catalog_write_service/test/unit/products/features/gettingproducts/v1/get_products_handler_unit_test.go @@ -0,0 +1,74 @@ +//go:build unit +// +build unit + +package v1 + +import ( + "net/http" + "testing" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" + gettingproductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" + + "github.com/stretchr/testify/suite" +) + +type getProductsHandlerUnitTests struct { + *unittest.UnitTestSharedFixture + handler cqrs.RequestHandlerWithRegisterer[*gettingproductsv1.GetProducts, *dtos.GetProductsResponseDto] +} + +func TestGetProductsUnit(t *testing.T) { + suite.Run( + t, + &getProductsHandlerUnitTests{ + UnitTestSharedFixture: unittest.NewUnitTestSharedFixture(t), + }, + ) +} + +func (c *getProductsHandlerUnitTests) SetupTest() { + // call base SetupTest hook before running child hook + c.UnitTestSharedFixture.SetupTest() + c.handler = gettingproductsv1.NewGetProductsHandler( + fxparams.ProductHandlerParams{ + CatalogsDBContext: c.CatalogDBContext, + Tracer: c.Tracer, + RabbitmqProducer: c.Bus, + Log: c.Log, + }) +} + +func (c *getProductsHandlerUnitTests) TearDownTest() { + // call base TearDownTest hook before running child hook + c.UnitTestSharedFixture.TearDownTest() +} + +func (c *getProductsHandlerUnitTests) Test_Handle_Should_Return_Products_Successfully() { + query, err := gettingproductsv1.NewGetProducts(utils.NewListQuery(10, 1)) + c.Require().NoError(err) + + res, err := c.handler.Handle(c.Ctx, query) + c.Require().NoError(err) + c.NotNil(res) + c.NotEmpty(res.Products) + c.Equal(len(c.Products), len(res.Products.Items)) +} + +func (c *getProductsHandlerUnitTests) Test_Handle_Should_Return_Error_For_Mapping_List_Result() { + query, err := gettingproductsv1.NewGetProducts(utils.NewListQuery(10, 1)) + c.Require().NoError(err) + + mapper.ClearMappings() + + res, err := c.handler.Handle(c.Ctx, query) + c.Require().Error(err) + c.True(customErrors.IsApplicationError(err, http.StatusInternalServerError)) + c.Nil(res) +} diff --git a/internal/services/catalog_write_service/test/unit/products/features/searchingproducts/v1/search_products_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/searchingproducts/v1/search_products_unit_test.go new file mode 100644 index 00000000..7f199cc5 --- /dev/null +++ b/internal/services/catalog_write_service/test/unit/products/features/searchingproducts/v1/search_products_unit_test.go @@ -0,0 +1,77 @@ +package v1 + +import ( + "net/http" + "testing" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" + searchingproductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" + + "github.com/stretchr/testify/suite" +) + +type searchProductsHandlerUnitTests struct { + *unittest.UnitTestSharedFixture + handler cqrs.RequestHandlerWithRegisterer[*searchingproductsv1.SearchProducts, *dtos.SearchProductsResponseDto] +} + +func TestSearchProductsUnit(t *testing.T) { + suite.Run( + t, + &searchProductsHandlerUnitTests{ + UnitTestSharedFixture: unittest.NewUnitTestSharedFixture(t), + }, + ) +} + +func (c *searchProductsHandlerUnitTests) SetupTest() { + // call base SetupTest hook before running child hook + c.UnitTestSharedFixture.SetupTest() + c.handler = searchingproductsv1.NewSearchProductsHandler( + fxparams.ProductHandlerParams{ + CatalogsDBContext: c.CatalogDBContext, + Tracer: c.Tracer, + RabbitmqProducer: c.Bus, + Log: c.Log, + }) +} + +func (c *searchProductsHandlerUnitTests) TearDownTest() { + // call base TearDownTest hook before running child hook + c.UnitTestSharedFixture.TearDownTest() +} + +func (c *searchProductsHandlerUnitTests) Test_Handle_Should_Return_Products_Successfully() { + query, err := searchingproductsv1.NewSearchProducts( + c.Products[0].Name, + utils.NewListQuery(10, 1), + ) + c.Require().NoError(err) + + res, err := c.handler.Handle(c.Ctx, query) + c.Require().NoError(err) + c.NotNil(res) + c.NotEmpty(res.Products) + c.Equal(len(res.Products.Items), 1) +} + +func (c *searchProductsHandlerUnitTests) Test_Handle_Should_Return_Error_For_Mapping_List_Result() { + query, err := searchingproductsv1.NewSearchProducts( + c.Products[0].Name, + utils.NewListQuery(10, 1), + ) + c.Require().NoError(err) + + mapper.ClearMappings() + + res, err := c.handler.Handle(c.Ctx, query) + c.Require().Error(err) + c.True(customErrors.IsApplicationError(err, http.StatusInternalServerError)) + c.Nil(res) +} diff --git a/internal/services/catalog_write_service/test/unit/products/features/updating_product/v1/commands/update_product_handler_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/updating_product/v1/commands/update_product_handler_unit_test.go deleted file mode 100644 index cbc520a2..00000000 --- a/internal/services/catalog_write_service/test/unit/products/features/updating_product/v1/commands/update_product_handler_unit_test.go +++ /dev/null @@ -1,150 +0,0 @@ -//go:build unit -// +build unit - -package commands - -import ( - "context" - "net/http" - "testing" - - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" - - "emperror.dev/errors" - "github.com/brianvoe/gofakeit/v6" - uuid "github.com/satori/go.uuid" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/suite" -) - -type updateProductHandlerUnitTests struct { - *unit_test.UnitTestSharedFixture -} - -func TestUpdateProductHandlerUnit(t *testing.T) { - suite.Run( - t, - &updateProductHandlerUnitTests{ - UnitTestSharedFixture: unit_test.NewUnitTestSharedFixture(t), - }, - ) -} - -func (c *updateProductHandlerUnitTests) Test_Handle_Should_Update_Product_With_Valid_Data() { - ctx := context.Background() - existing := c.Items[0] - - updateProductCommand, err := v1.NewUpdateProduct( - existing.ProductId, - gofakeit.Name(), - gofakeit.EmojiDescription(), - existing.Price, - ) - c.Require().NoError(err) - - updated := &models.Product{ - ProductId: existing.ProductId, - Name: updateProductCommand.Name, - Description: updateProductCommand.Description, - UpdatedAt: updateProductCommand.UpdatedAt, - CreatedAt: existing.CreatedAt, - Price: existing.Price, - } - - c.ProductRepository.On("GetProductById", mock.Anything, existing.ProductId). - Once(). - Return(existing, nil) - - c.ProductRepository.On("UpdateProduct", mock.Anything, mock.Anything). - Once(). - Return(updated, nil) - - updateProductHandler := v1.NewUpdateProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) - - _, err = updateProductHandler.Handle(ctx, updateProductCommand) - c.Require().NoError(err) - - c.Uow.AssertNumberOfCalls(c.T(), "Do", 1) - c.ProductRepository.AssertNumberOfCalls(c.T(), "GetProductById", 1) - c.ProductRepository.AssertNumberOfCalls(c.T(), "UpdateProduct", 1) - c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 1) -} - -func (c *updateProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_NotFound_Item() { - ctx := context.Background() - id := uuid.NewV4() - - command, err := v1.NewUpdateProduct( - id, - gofakeit.Name(), - gofakeit.EmojiDescription(), - gofakeit.Price(150, 6000), - ) - c.Require().NoError(err) - - c.ProductRepository.On("GetProductById", mock.Anything, mock.Anything). - Once(). - Return(nil, errors.New("error notfound product")) - - updateProductHandler := v1.NewUpdateProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) - dto, err := updateProductHandler.Handle(ctx, command) - - c.Uow.AssertNumberOfCalls(c.T(), "Do", 1) - c.ProductRepository.AssertNumberOfCalls(c.T(), "GetProductById", 1) - c.ProductRepository.AssertNumberOfCalls(c.T(), "UpdateProduct", 0) - c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 0) - c.True(customErrors.IsApplicationError(err, http.StatusNotFound)) - c.ErrorContains(err, "error notfound product") - c.NotNil(dto) -} - -func (c *updateProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Error_In_Bus() { - ctx := context.Background() - existing := c.Items[0] - - updateProductCommand, err := v1.NewUpdateProduct( - existing.ProductId, - gofakeit.Name(), - gofakeit.EmojiDescription(), - existing.Price, - ) - c.Require().NoError(err) - - updated := &models.Product{ - ProductId: existing.ProductId, - Name: updateProductCommand.Name, - Description: updateProductCommand.Description, - UpdatedAt: updateProductCommand.UpdatedAt, - CreatedAt: existing.CreatedAt, - Price: existing.Price, - } - - c.ProductRepository.On("GetProductById", mock.Anything, existing.ProductId). - Once(). - Return(existing, nil) - - c.ProductRepository.On("UpdateProduct", mock.Anything, mock.Anything). - Once(). - Return(updated, nil) - - // override called mock - // https://github.com/stretchr/testify/issues/558 - c.Bus.Mock.ExpectedCalls = nil - c.Bus.On("PublishMessage", mock.Anything, mock.Anything, mock.Anything). - Once(). - Return(errors.New("error in the publish message")) - - updateProductHandler := v1.NewUpdateProductHandler(c.Log, c.Uow, c.Bus, c.Tracer) - dto, err := updateProductHandler.Handle(ctx, updateProductCommand) - - c.Uow.AssertNumberOfCalls(c.T(), "Do", 1) - c.ProductRepository.AssertNumberOfCalls(c.T(), "UpdateProduct", 1) - c.ProductRepository.AssertNumberOfCalls(c.T(), "GetProductById", 1) - c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 1) - c.ErrorContains(err, "error in the publish message") - c.ErrorContains(err, "error in publishing 'ProductUpdated' message") - c.NotNil(dto) -} diff --git a/internal/services/catalog_write_service/test/unit/products/features/updatingproduct/v1/update_product_handler_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/updatingproduct/v1/update_product_handler_unit_test.go new file mode 100644 index 00000000..efd27042 --- /dev/null +++ b/internal/services/catalog_write_service/test/unit/products/features/updatingproduct/v1/update_product_handler_unit_test.go @@ -0,0 +1,133 @@ +//go:build unit +// +build unit + +package v1 + +import ( + "fmt" + "net/http" + "testing" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" + updatingoroductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" + + "emperror.dev/errors" + "github.com/brianvoe/gofakeit/v6" + "github.com/mehdihadeli/go-mediatr" + uuid "github.com/satori/go.uuid" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/suite" +) + +type updateProductHandlerUnitTests struct { + *unittest.UnitTestSharedFixture + handler cqrs.RequestHandlerWithRegisterer[*updatingoroductsv1.UpdateProduct, *mediatr.Unit] +} + +func TestUpdateProductHandlerUnit(t *testing.T) { + suite.Run( + t, + &updateProductHandlerUnitTests{ + UnitTestSharedFixture: unittest.NewUnitTestSharedFixture(t), + }, + ) +} + +func (c *updateProductHandlerUnitTests) SetupTest() { + // call base SetupTest hook before running child hook + c.UnitTestSharedFixture.SetupTest() + c.handler = updatingoroductsv1.NewUpdateProductHandler( + fxparams.ProductHandlerParams{ + CatalogsDBContext: c.CatalogDBContext, + Tracer: c.Tracer, + RabbitmqProducer: c.Bus, + Log: c.Log, + }, + ) +} + +func (c *updateProductHandlerUnitTests) TearDownTest() { + // call base TearDownTest hook before running child hook + c.UnitTestSharedFixture.TearDownTest() +} + +func (c *updateProductHandlerUnitTests) Test_Handle_Should_Update_Product_With_Valid_Data() { + existing := c.Products[0] + + updateProductCommand, err := updatingoroductsv1.NewUpdateProduct( + existing.ProductId, + gofakeit.Name(), + gofakeit.EmojiDescription(), + existing.Price, + ) + c.Require().NoError(err) + + c.BeginTx() + _, err = c.handler.Handle(c.Ctx, updateProductCommand) + c.CommitTx() + + c.Require().NoError(err) + + updatedProduct, err := c.CatalogDBContext.FindProductByID( + c.Ctx, + updateProductCommand.ProductID, + ) + c.Require().NoError(err) + + c.Assert().Equal(updatedProduct.ProductId, updateProductCommand.ProductID) + c.Assert().Equal(updatedProduct.Name, updateProductCommand.Name) + c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 1) +} + +func (c *updateProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_NotFound_Item() { + id := uuid.NewV4() + + command, err := updatingoroductsv1.NewUpdateProduct( + id, + gofakeit.Name(), + gofakeit.EmojiDescription(), + gofakeit.Price(150, 6000), + ) + c.Require().NoError(err) + + c.BeginTx() + _, err = c.handler.Handle(c.Ctx, command) + c.CommitTx() + + c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 0) + c.True(customErrors.IsApplicationError(err, http.StatusNotFound)) + c.ErrorContains( + err, + fmt.Sprintf("product with id `%s` not found", id.String()), + ) +} + +func (c *updateProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Error_In_Bus() { + existing := c.Products[0] + + updateProductCommand, err := updatingoroductsv1.NewUpdateProduct( + existing.ProductId, + gofakeit.Name(), + gofakeit.EmojiDescription(), + existing.Price, + ) + c.Require().NoError(err) + + // override called mock + // https://github.com/stretchr/testify/issues/558 + c.Bus.Mock.ExpectedCalls = nil + c.Bus.On("PublishMessage", mock.Anything, mock.Anything, mock.Anything). + Once(). + Return(errors.New("error in the publish message")) + + c.BeginTx() + _, err = c.handler.Handle(c.Ctx, updateProductCommand) + c.CommitTx() + + c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 1) + c.ErrorContains(err, "error in the publish message") + c.ErrorContains(err, "error in publishing 'ProductUpdated' message") +} diff --git a/internal/services/catalog_write_service/test/unit/products/features/updating_product/v1/commands/update_product_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/updatingproduct/v1/update_product_unit_test.go similarity index 88% rename from internal/services/catalog_write_service/test/unit/products/features/updating_product/v1/commands/update_product_unit_test.go rename to internal/services/catalog_write_service/test/unit/products/features/updatingproduct/v1/update_product_unit_test.go index 9b2d19ec..c82b4c60 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/updating_product/v1/commands/update_product_unit_test.go +++ b/internal/services/catalog_write_service/test/unit/products/features/updatingproduct/v1/update_product_unit_test.go @@ -1,13 +1,13 @@ //go:build unit // +build unit -package commands +package v1 import ( "testing" - v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updating_product/v1" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" + v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" "github.com/brianvoe/gofakeit/v6" uuid "github.com/satori/go.uuid" @@ -15,13 +15,13 @@ import ( ) type updateProductUnitTests struct { - *unit_test.UnitTestSharedFixture + *unittest.UnitTestSharedFixture } func TestUpdateProductUnit(t *testing.T) { suite.Run( t, - &updateProductUnitTests{UnitTestSharedFixture: unit_test.NewUnitTestSharedFixture(t)}, + &updateProductUnitTests{UnitTestSharedFixture: unittest.NewUnitTestSharedFixture(t)}, ) } diff --git a/internal/services/catalog_write_service/test/unit/products/mappings_profile_test.go b/internal/services/catalog_write_service/test/unit/products/mappings_profile_test.go index ac523994..38a45fbd 100644 --- a/internal/services/catalog_write_service/test/unit/products/mappings_profile_test.go +++ b/internal/services/catalog_write_service/test/unit/products/mappings_profile_test.go @@ -10,7 +10,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/test_fixtures/unit_test" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" "github.com/brianvoe/gofakeit/v6" uuid "github.com/satori/go.uuid" @@ -18,13 +18,13 @@ import ( ) type mappingProfileUnitTests struct { - *unit_test.UnitTestSharedFixture + *unittest.UnitTestSharedFixture } func TestMappingProfileUnit(t *testing.T) { suite.Run( t, - &mappingProfileUnitTests{UnitTestSharedFixture: unit_test.NewUnitTestSharedFixture(t)}, + &mappingProfileUnitTests{UnitTestSharedFixture: unittest.NewUnitTestSharedFixture(t)}, ) } diff --git a/internal/services/order_service/internal/orders/features/creating_order/v1/dtos/create_order_request_dto.go b/internal/services/order_service/internal/orders/features/creating_order/v1/dtos/create_order_request_dto.go index 6b63171c..22c26e63 100644 --- a/internal/services/order_service/internal/orders/features/creating_order/v1/dtos/create_order_request_dto.go +++ b/internal/services/order_service/internal/orders/features/creating_order/v1/dtos/create_order_request_dto.go @@ -1,7 +1,7 @@ package dtos import ( - customTypes "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/custom_types" + customTypes "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/customtypes" dtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/dtos/v1" ) diff --git a/internal/services/order_service/internal/orders/features/creating_order/v1/events/domain_events/order_created.go b/internal/services/order_service/internal/orders/features/creating_order/v1/events/domain_events/order_created.go index 4c9d2af0..10848c72 100644 --- a/internal/services/order_service/internal/orders/features/creating_order/v1/events/domain_events/order_created.go +++ b/internal/services/order_service/internal/orders/features/creating_order/v1/events/domain_events/order_created.go @@ -5,7 +5,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/domain" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" dtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/dtos/v1" domainExceptions "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/exceptions/domain_exceptions" diff --git a/internal/services/order_service/internal/orders/features/creating_order/v1/events/integration_events/order_created.go b/internal/services/order_service/internal/orders/features/creating_order/v1/events/integration_events/order_created.go index 2487ef87..1ad32d0b 100644 --- a/internal/services/order_service/internal/orders/features/creating_order/v1/events/integration_events/order_created.go +++ b/internal/services/order_service/internal/orders/features/creating_order/v1/events/integration_events/order_created.go @@ -1,7 +1,7 @@ package integrationEvents import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" dtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/dtos/v1" uuid "github.com/satori/go.uuid" diff --git a/internal/services/order_service/internal/orders/models/orders/aggregate/order.go b/internal/services/order_service/internal/orders/models/orders/aggregate/order.go index 19812c31..7b3f17d3 100644 --- a/internal/services/order_service/internal/orders/models/orders/aggregate/order.go +++ b/internal/services/order_service/internal/orders/models/orders/aggregate/order.go @@ -10,7 +10,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/models" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/type_mappper" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" dtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/dtos/v1" domainExceptions "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/exceptions/domain_exceptions" createOrderDomainEventsV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/creating_order/v1/events/domain_events" diff --git a/internal/services/order_service/internal/orders/projections/mongo_order_projection.go b/internal/services/order_service/internal/orders/projections/mongo_order_projection.go index 559d4612..0c5fc68d 100644 --- a/internal/services/order_service/internal/orders/projections/mongo_order_projection.go +++ b/internal/services/order_service/internal/orders/projections/mongo_order_projection.go @@ -4,12 +4,12 @@ import ( "context" "fmt" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/producer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/contracts/projection" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/models" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/producer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" diff --git a/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go b/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go index 35130df2..c3dbb895 100644 --- a/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go +++ b/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go @@ -3,9 +3,8 @@ package infrastructure import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/pipelines" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" - pipelines2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/mediatr/pipelines" + metricspipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/mediatr/pipelines" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" tracingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/mediatr/pipelines" @@ -26,16 +25,16 @@ func NewInfrastructureConfigurator( func (ic *InfrastructureConfigurator) ConfigInfrastructures() { ic.ResolveFunc( - func(logger logger.Logger, tracer tracing.AppTracer, metrics metrics.AppMetrics) error { + func(l logger.Logger, tracer tracing.AppTracer, metrics metrics.AppMetrics) error { err := mediatr.RegisterRequestPipelineBehaviors( - pipelines.NewLoggingPipeline(logger), + loggingpipelines.NewMediatorLoggingPipeline(l), tracingpipelines.NewMediatorTracingPipeline( tracer, - tracingpipelines.WithLogger(logger), + tracingpipelines.WithLogger(l), ), - pipelines2.NewMediatorMetricsPipeline( + metricspipelines.NewMediatorMetricsPipeline( metrics, - pipelines2.WithLogger(logger), + metricspipelines.WithLogger(l), ), ) diff --git a/internal/services/order_service/internal/shared/test_fixtures/integration/integration_test_fixture.go b/internal/services/order_service/internal/shared/test_fixtures/integration/integration_test_fixture.go index 91032d12..c2d0f976 100644 --- a/internal/services/order_service/internal/shared/test_fixtures/integration/integration_test_fixture.go +++ b/internal/services/order_service/internal/shared/test_fixtures/integration/integration_test_fixture.go @@ -4,11 +4,11 @@ import ( "context" "testing" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/bus" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/contracts/store" config3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/eventstroredb/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/messaging/bus" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" @@ -85,8 +85,8 @@ func NewIntegrationTestSharedFixture( return shared } -func (i *IntegrationTestSharedFixture) InitializeTest() { - i.Log.Info("InitializeTest started") +func (i *IntegrationTestSharedFixture) SetupTest() { + i.Log.Info("SetupTest started") // seed data in each test res, err := seedReadModelData(i.mongoClient, i.MongoDbOptions.Database) @@ -96,8 +96,8 @@ func (i *IntegrationTestSharedFixture) InitializeTest() { i.Items = res } -func (i *IntegrationTestSharedFixture) DisposeTest() { - i.Log.Info("DisposeTest started") +func (i *IntegrationTestSharedFixture) TearDownTest() { + i.Log.Info("TearDownTest started") // cleanup test containers with their hooks if err := i.cleanupRabbitmqData(); err != nil { diff --git a/internal/services/order_service/test/end_to_end/orders/features/creating_order/v1/create_order_test.go b/internal/services/order_service/test/end_to_end/orders/features/creating_order/v1/create_order_test.go index 378e93c8..f1a35a82 100644 --- a/internal/services/order_service/test/end_to_end/orders/features/creating_order/v1/create_order_test.go +++ b/internal/services/order_service/test/end_to_end/orders/features/creating_order/v1/create_order_test.go @@ -9,7 +9,7 @@ import ( "testing" "time" - customTypes "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/custom_types" + customTypes "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/customtypes" dtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/creating_order/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/shared/test_fixtures/integration" @@ -39,12 +39,12 @@ var _ = Describe("CreateOrder Feature", func() { ctx = context.Background() By("Seeding the required data") - integrationFixture.InitializeTest() + integrationFixture.SetupTest() }) _ = AfterEach(func() { By("Cleanup test data") - integrationFixture.DisposeTest() + integrationFixture.TearDownTest() }) // "Scenario" for testing the creation of an order with valid input diff --git a/internal/services/order_service/test/end_to_end/orders/features/getting_order_by_id/v1/get_order_by_id_test.go b/internal/services/order_service/test/end_to_end/orders/features/getting_order_by_id/v1/get_order_by_id_test.go index 89242231..19e81a9f 100644 --- a/internal/services/order_service/test/end_to_end/orders/features/getting_order_by_id/v1/get_order_by_id_test.go +++ b/internal/services/order_service/test/end_to_end/orders/features/getting_order_by_id/v1/get_order_by_id_test.go @@ -34,14 +34,14 @@ var _ = Describe("GetOrderById Feature", func() { ctx = context.Background() By("Seeding the required data") - integrationFixture.InitializeTest() + integrationFixture.SetupTest() id = integrationFixture.Items[0].Id }) _ = AfterEach(func() { By("Cleanup test data") - integrationFixture.DisposeTest() + integrationFixture.TearDownTest() }) // "Scenario" for testing the retrieval of an order by a valid ID diff --git a/internal/services/order_service/test/integration/orders/features/creating_order/v1/create_order_test.go b/internal/services/order_service/test/integration/orders/features/creating_order/v1/create_order_test.go index 4238121a..78aefa5e 100644 --- a/internal/services/order_service/test/integration/orders/features/creating_order/v1/create_order_test.go +++ b/internal/services/order_service/test/integration/orders/features/creating_order/v1/create_order_test.go @@ -46,14 +46,14 @@ var _ = Describe("Create Order Feature", func() { _ = BeforeEach(func() { By("Seeding the required data") - integrationFixture.InitializeTest() + integrationFixture.SetupTest() // id = integrationFixture.Items[0].OrderId }) _ = AfterEach(func() { By("Cleanup test data") - integrationFixture.DisposeTest() + integrationFixture.TearDownTest() }) _ = BeforeSuite(func() { diff --git a/internal/services/order_service/test/integration/orders/features/getting_order_by_id/v1/get_order_by_id_test.go b/internal/services/order_service/test/integration/orders/features/getting_order_by_id/v1/get_order_by_id_test.go index 90a9c30b..c305c7bc 100644 --- a/internal/services/order_service/test/integration/orders/features/getting_order_by_id/v1/get_order_by_id_test.go +++ b/internal/services/order_service/test/integration/orders/features/getting_order_by_id/v1/get_order_by_id_test.go @@ -38,7 +38,7 @@ var _ = Describe("Get Order By Id Feature", func() { _ = BeforeEach(func() { By("Seeding the required data") - integrationFixture.InitializeTest() + integrationFixture.SetupTest() idString := integrationFixture.Items[0].Id id, err = uuid.FromString(idString) @@ -47,7 +47,7 @@ var _ = Describe("Get Order By Id Feature", func() { _ = AfterEach(func() { By("Cleanup test data") - integrationFixture.DisposeTest() + integrationFixture.TearDownTest() }) _ = BeforeSuite(func() { From dfa0d5056e31577a1e612638428c8abc49b1cf1b Mon Sep 17 00:00:00 2001 From: mehdihadeli Date: Wed, 29 Nov 2023 17:22:16 +0330 Subject: [PATCH 09/15] feat: :sparkles: supporting Inbox and Outbox Pattern #70 --- internal/pkg/config/config_helper.go | 26 +-- .../pkg/config/environment/environment.go | 77 +------- internal/pkg/config/environment/helpers.go | 90 ++++++++++ .../message_persistence_repository.go | 14 +- .../messaging/persistmessage/store_message.go | 14 +- .../constants/constants.go | 0 .../contracts/gorm_context.go | 0 .../pkg/{postgresGorm => postgresgorm}/db.go | 3 +- .../gorm_options.go | 2 +- .../gorm_options_test.go | 2 +- .../gorm_postgres_fx.go | 2 +- .../{postgresGorm => postgresgorm}/health.go | 2 +- .../{postgresGorm => postgresgorm}/helpers.go | 2 +- .../helpers/helpers.go | 18 +- .../mediator_transaction_pipeline.go | 2 +- .../repository/gorm_generic_repository.go | 2 +- .../gorm_generic_repository_test.go | 4 +- .../message_persistence_dbcontext.go | 21 +-- .../message_persistence_repository.go | 170 +++++++++++++++--- .../message_persistence_repository_test.go | 159 ++++++++++++++++ .../postgres_messaging_fx.go | 24 +++ .../containers/contracts/gorm_container.go | 2 +- .../dockertest/gorm/gorm_container.go | 2 +- .../dockertest/gorm/gorm_container_test.go | 2 +- .../containers/dockertest/gorm/gorm_fx.go | 2 +- .../containers/gnomock/gorm/gorm_container.go | 2 +- .../testcontainer/gorm/gorm_container.go | 2 +- .../testcontainer/gorm/gorm_container_test.go | 2 +- .../containers/testcontainer/gorm/gorm_fx.go | 2 +- .../infrastructure_configurator.go | 2 +- .../cmd/migration/main.go | 2 +- .../data/models/product_data_model.go | 2 + .../repositories/pg_product_repository.go | 2 +- .../v1/create_product_handler.go | 7 +- .../v1/delete_product_handler.go | 7 +- .../v1/get_products_handler.go | 4 +- .../v1/search_products_handler.go | 2 +- .../v1/update_product_handler.go | 9 +- .../internal/shared/app/test/test_app.go | 2 +- .../infrastructure_configurator.go | 2 +- .../infrastructure/infrastructure_fx.go | 6 +- .../data/dbcontext/catalogs_dbcontext.go | 39 +++- .../data/dbcontext/catalogs_dbcontext_test.go | 2 +- .../integration/integration_test_fixture.go | 2 +- .../unittest/unit_test_fixture.go | 70 ++++++-- .../v1/create_product_handler_unit_test.go | 5 +- 46 files changed, 605 insertions(+), 210 deletions(-) create mode 100644 internal/pkg/config/environment/helpers.go rename internal/pkg/{postgresGorm => postgresgorm}/constants/constants.go (100%) rename internal/pkg/{postgresGorm => postgresgorm}/contracts/gorm_context.go (100%) rename internal/pkg/{postgresGorm => postgresgorm}/db.go (99%) rename internal/pkg/{postgresGorm => postgresgorm}/gorm_options.go (98%) rename internal/pkg/{postgresGorm => postgresgorm}/gorm_options_test.go (87%) rename internal/pkg/{postgresGorm => postgresgorm}/gorm_postgres_fx.go (95%) rename internal/pkg/{postgresGorm => postgresgorm}/health.go (95%) rename internal/pkg/{postgresGorm => postgresgorm}/helpers.go (98%) rename internal/pkg/{postgresGorm => postgresgorm}/helpers/helpers.go (71%) rename internal/pkg/{postgresGorm => postgresgorm}/mediatr/pipelines/mediator_transaction_pipeline.go (98%) rename internal/pkg/{postgresGorm => postgresgorm}/repository/gorm_generic_repository.go (99%) rename internal/pkg/{postgresGorm => postgresgorm}/repository/gorm_generic_repository_test.go (99%) create mode 100644 internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository_test.go create mode 100644 internal/pkg/postgresmessaging/postgres_messaging_fx.go diff --git a/internal/pkg/config/config_helper.go b/internal/pkg/config/config_helper.go index 968b1415..2054bd76 100644 --- a/internal/pkg/config/config_helper.go +++ b/internal/pkg/config/config_helper.go @@ -26,11 +26,11 @@ func BindConfigKey[T any]( ) (T, error) { var configPath string - environment := environment.Environment("") + currentEnv := environment.Environment("") if len(environments) > 0 { - environment = environments[0] + currentEnv = environments[0] } else { - environment = constants.Dev + currentEnv = constants.Dev } cfg := typeMapper.GenericInstanceByT[T]() @@ -41,7 +41,7 @@ func BindConfigKey[T any]( // https://articles.wesionary.team/environment-variable-configuration-in-your-golang-project-using-viper-4e8289ef664d // when we `Set` a viper with string value, we should get it from viper with `viper.GetString`, elsewhere we get empty string - // load `config path` from environment variable or viper internal registry + // load `config path` from env variable or viper internal registry configPathFromEnv := viper.GetString(constants.ConfigPath) if configPathFromEnv != "" { @@ -50,8 +50,11 @@ func BindConfigKey[T any]( // https://stackoverflow.com/questions/31873396/is-it-possible-to-get-the-current-root-of-package-structure-as-a-string-in-golan // https://stackoverflow.com/questions/18537257/how-to-get-the-directory-of-the-currently-running-file appRootPath := viper.GetString(constants.AppRootPath) + if appRootPath == "" { + appRootPath = environment.GetProjectRootWorkingDirectory() + } - d, err := searchForConfigFileDir(appRootPath, environment) + d, err := searchForConfigFileDir(appRootPath, currentEnv) if err != nil { return *new(T), err } @@ -60,7 +63,7 @@ func BindConfigKey[T any]( } // https://github.com/spf13/viper/issues/390#issuecomment-718756752 - viper.SetConfigName(fmt.Sprintf("config.%s", environment)) + viper.SetConfigName(fmt.Sprintf("config.%s", currentEnv)) viper.AddConfigPath(configPath) viper.SetConfigType(constants.Json) @@ -104,7 +107,7 @@ func BindConfigKey[T any]( // error: An error indicating any issues encountered during the search. func searchForConfigFileDir( rootDir string, - environment environment.Environment, + env environment.Environment, ) (string, error) { var result string @@ -116,23 +119,24 @@ func searchForConfigFileDir( return err } - // Check if the file is named "config.%s.json" (replace %s with the environment) + // Check if the file is named "config.%s.json" (replace %s with the env) if !info.IsDir() && strings.EqualFold( info.Name(), - fmt.Sprintf("config.%s.json", environment), + fmt.Sprintf("config.%s.json", env), ) || strings.EqualFold( info.Name(), - fmt.Sprintf("config.%s.yaml", environment), + fmt.Sprintf("config.%s.yaml", env), ) || strings.EqualFold( info.Name(), - fmt.Sprintf("config.%s.yml", environment), + fmt.Sprintf("config.%s.yml", env), ) { // Get the directory name containing the config file dir := filepath.Dir(path) result = dir + return filepath.SkipDir // Skip further traversal } diff --git a/internal/pkg/config/environment/environment.go b/internal/pkg/config/environment/environment.go index 7887fc35..f48eaf64 100644 --- a/internal/pkg/config/environment/environment.go +++ b/internal/pkg/config/environment/environment.go @@ -4,7 +4,6 @@ import ( "log" "os" "path/filepath" - "strings" "syscall" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/constants" @@ -42,7 +41,7 @@ func ConfigAppEnv(environments ...Environment) Environment { setRootWorkingDirectoryEnvironment() - fixTestEnvironmentWorkingDirectory() + FixProjectRootWorkingDirectoryPath() manualEnv := os.Getenv(constants.AppEnv) @@ -108,80 +107,8 @@ func loadEnvFilesRecursive() error { } func setRootWorkingDirectoryEnvironment() { - var rootWorkingDirectory string - // https://articles.wesionary.team/environment-variable-configuration-in-your-golang-project-using-viper-4e8289ef664d - // when we `Set` a viper with string value, we should get it from viper with `viper.GetString`, elsewhere we get empty string - // viper will get it from `os env` or a .env file - pn := viper.GetString(constants.PROJECT_NAME_ENV) - if pn != "" { - rootWorkingDirectory = getRootDirectoryFromProjectName(pn) - } else { - wd, _ := os.Getwd() - dir, err := searchRootDirectory(wd) - if err != nil { - log.Fatal(err) - } - rootWorkingDirectory = dir - } - - absoluteRootWorkingDirectory, _ := filepath.Abs(rootWorkingDirectory) + absoluteRootWorkingDirectory := GetProjectRootWorkingDirectory() // when we `Set` a viper with string value, we should get it from viper with `viper.GetString`, elsewhere we get empty string viper.Set(constants.AppRootPath, absoluteRootWorkingDirectory) } - -func fixTestEnvironmentWorkingDirectory() { - currentWD, _ := os.Getwd() - log.Printf("Current test working directory is: %s", currentWD) - - rootDir := viper.GetString(constants.AppRootPath) - if rootDir != "" { - _ = os.Chdir(rootDir) - - newWD, _ := os.Getwd() - log.Printf("New test working directory is: %s", newWD) - } -} - -func getRootDirectoryFromProjectName(pn string) string { - // set root working directory of our app in the viper - // https://stackoverflow.com/a/47785436/581476 - wd, _ := os.Getwd() - - for !strings.HasSuffix(wd, pn) { - wd = filepath.Dir(wd) - } - - return wd -} - -func searchRootDirectory( - dir string, -) (string, error) { - // List files and directories in the current directory - files, err := os.ReadDir(dir) - if err != nil { - return "", errors.WrapIf(err, "Error reading directory") - } - - for _, file := range files { - if !file.IsDir() { - fileName := file.Name() - if strings.EqualFold( - fileName, - "go.mod", - ) { - return dir, nil - } - } - } - - // If no config file found in this directory, recursively search its parent - parentDir := filepath.Dir(dir) - if parentDir == dir { - // We've reached the root directory, and no go.mod file was found - return "", errors.WrapIf(err, "No go.mod file found") - } - - return searchRootDirectory(parentDir) -} diff --git a/internal/pkg/config/environment/helpers.go b/internal/pkg/config/environment/helpers.go new file mode 100644 index 00000000..1af013b9 --- /dev/null +++ b/internal/pkg/config/environment/helpers.go @@ -0,0 +1,90 @@ +package environment + +import ( + "log" + "os" + "path/filepath" + "strings" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/constants" + + "emperror.dev/errors" + "github.com/spf13/viper" +) + +func FixProjectRootWorkingDirectoryPath() { + currentWD, _ := os.Getwd() + log.Printf("Current working directory is: `%s`", currentWD) + + rootDir := GetProjectRootWorkingDirectory() + // change working directory + _ = os.Chdir(rootDir) + newWD, _ := os.Getwd() + + log.Printf("New fixed working directory is: `%s`", newWD) +} + +func GetProjectRootWorkingDirectory() string { + var rootWorkingDirectory string + // https://articles.wesionary.team/environment-variable-configuration-in-your-golang-project-using-viper-4e8289ef664d + // when we `Set` a viper with string value, we should get it from viper with `viper.GetString`, elsewhere we get empty string + // viper will get it from `os env` or a .env file + pn := viper.GetString(constants.PROJECT_NAME_ENV) + if pn != "" { + rootWorkingDirectory = getProjectRootDirectoryFromProjectName(pn) + } else { + wd, _ := os.Getwd() + dir, err := searchRootDirectory(wd) + if err != nil { + log.Fatal(err) + } + rootWorkingDirectory = dir + } + + absoluteRootWorkingDirectory, _ := filepath.Abs(rootWorkingDirectory) + + return absoluteRootWorkingDirectory +} + +func getProjectRootDirectoryFromProjectName(pn string) string { + // set root working directory of our app in the viper + // https://stackoverflow.com/a/47785436/581476 + wd, _ := os.Getwd() + + for !strings.HasSuffix(wd, pn) { + wd = filepath.Dir(wd) + } + + return wd +} + +func searchRootDirectory( + dir string, +) (string, error) { + // List files and directories in the current directory + files, err := os.ReadDir(dir) + if err != nil { + return "", errors.WrapIf(err, "Error reading directory") + } + + for _, file := range files { + if !file.IsDir() { + fileName := file.Name() + if strings.EqualFold( + fileName, + "go.mod", + ) { + return dir, nil + } + } + } + + // If no config file found in this directory, recursively search its parent + parentDir := filepath.Dir(dir) + if parentDir == dir { + // We've reached the root directory, and no go.mod file was found + return "", errors.WrapIf(err, "No go.mod file found") + } + + return searchRootDirectory(parentDir) +} diff --git a/internal/pkg/core/messaging/persistmessage/message_persistence_repository.go b/internal/pkg/core/messaging/persistmessage/message_persistence_repository.go index efff7d2f..59d5c3f3 100644 --- a/internal/pkg/core/messaging/persistmessage/message_persistence_repository.go +++ b/internal/pkg/core/messaging/persistmessage/message_persistence_repository.go @@ -1,21 +1,25 @@ package persistmessage -import "context" +import ( + "context" + + uuid "github.com/satori/go.uuid" +) type MessagePersistenceRepository interface { Add(ctx context.Context, storeMessage *StoreMessage) error Update(ctx context.Context, storeMessage *StoreMessage) error ChangeState( ctx context.Context, - messageID string, + messageID uuid.UUID, status MessageStatus, ) error - GetAll(ctx context.Context) ([]*StoreMessage, error) + GetAllActive(ctx context.Context) ([]*StoreMessage, error) GetByFilter( ctx context.Context, predicate func(*StoreMessage) bool, ) ([]*StoreMessage, error) - GetById(ctx context.Context, id string) (*StoreMessage, error) + GetById(ctx context.Context, id uuid.UUID) (*StoreMessage, error) Remove(ctx context.Context, storeMessage *StoreMessage) (bool, error) - CleanupMessages() + CleanupMessages(ctx context.Context) error } diff --git a/internal/pkg/core/messaging/persistmessage/store_message.go b/internal/pkg/core/messaging/persistmessage/store_message.go index c8fd3025..44ab41c0 100644 --- a/internal/pkg/core/messaging/persistmessage/store_message.go +++ b/internal/pkg/core/messaging/persistmessage/store_message.go @@ -1,6 +1,10 @@ package persistmessage -import "time" +import ( + "time" + + uuid "github.com/satori/go.uuid" +) type MessageDeliveryType int @@ -18,7 +22,7 @@ const ( ) type StoreMessage struct { - ID string + ID uuid.UUID `gorm:"primaryKey"` DataType string Data string Created time.Time @@ -28,7 +32,7 @@ type StoreMessage struct { } func NewStoreMessage( - id string, + id uuid.UUID, dataType string, data string, deliveryType MessageDeliveryType, @@ -51,3 +55,7 @@ func (sm *StoreMessage) ChangeState(messageStatus MessageStatus) { func (sm *StoreMessage) IncreaseRetry() { sm.RetryCount++ } + +func (sm *StoreMessage) TableName() string { + return "store_messages" +} diff --git a/internal/pkg/postgresGorm/constants/constants.go b/internal/pkg/postgresgorm/constants/constants.go similarity index 100% rename from internal/pkg/postgresGorm/constants/constants.go rename to internal/pkg/postgresgorm/constants/constants.go diff --git a/internal/pkg/postgresGorm/contracts/gorm_context.go b/internal/pkg/postgresgorm/contracts/gorm_context.go similarity index 100% rename from internal/pkg/postgresGorm/contracts/gorm_context.go rename to internal/pkg/postgresgorm/contracts/gorm_context.go diff --git a/internal/pkg/postgresGorm/db.go b/internal/pkg/postgresgorm/db.go similarity index 99% rename from internal/pkg/postgresGorm/db.go rename to internal/pkg/postgresgorm/db.go index 0e147cf3..6e4afe5e 100644 --- a/internal/pkg/postgresGorm/db.go +++ b/internal/pkg/postgresgorm/db.go @@ -1,4 +1,4 @@ -package postgresGorm +package postgresgorm import ( "database/sql" @@ -66,6 +66,7 @@ func createInMemoryDB() (*gorm.DB, error) { &gorm.Config{ Logger: gromlog.NewGormCustomLogger(defaultlogger.GetLogger()), }) + return db, err } diff --git a/internal/pkg/postgresGorm/gorm_options.go b/internal/pkg/postgresgorm/gorm_options.go similarity index 98% rename from internal/pkg/postgresGorm/gorm_options.go rename to internal/pkg/postgresgorm/gorm_options.go index b9c04226..e7e33907 100644 --- a/internal/pkg/postgresGorm/gorm_options.go +++ b/internal/pkg/postgresgorm/gorm_options.go @@ -1,4 +1,4 @@ -package postgresGorm +package postgresgorm import ( "fmt" diff --git a/internal/pkg/postgresGorm/gorm_options_test.go b/internal/pkg/postgresgorm/gorm_options_test.go similarity index 87% rename from internal/pkg/postgresGorm/gorm_options_test.go rename to internal/pkg/postgresgorm/gorm_options_test.go index b8ead84f..359360cd 100644 --- a/internal/pkg/postgresGorm/gorm_options_test.go +++ b/internal/pkg/postgresgorm/gorm_options_test.go @@ -1,4 +1,4 @@ -package postgresGorm +package postgresgorm import ( "testing" diff --git a/internal/pkg/postgresGorm/gorm_postgres_fx.go b/internal/pkg/postgresgorm/gorm_postgres_fx.go similarity index 95% rename from internal/pkg/postgresGorm/gorm_postgres_fx.go rename to internal/pkg/postgresgorm/gorm_postgres_fx.go index e7c9b253..44fc6611 100644 --- a/internal/pkg/postgresGorm/gorm_postgres_fx.go +++ b/internal/pkg/postgresgorm/gorm_postgres_fx.go @@ -1,4 +1,4 @@ -package postgresGorm +package postgresgorm import ( "fmt" diff --git a/internal/pkg/postgresGorm/health.go b/internal/pkg/postgresgorm/health.go similarity index 95% rename from internal/pkg/postgresGorm/health.go rename to internal/pkg/postgresgorm/health.go index 717e5702..539a81a2 100644 --- a/internal/pkg/postgresGorm/health.go +++ b/internal/pkg/postgresgorm/health.go @@ -1,4 +1,4 @@ -package postgresGorm +package postgresgorm import ( "context" diff --git a/internal/pkg/postgresGorm/helpers.go b/internal/pkg/postgresgorm/helpers.go similarity index 98% rename from internal/pkg/postgresGorm/helpers.go rename to internal/pkg/postgresgorm/helpers.go index 7b1c070a..bd4e0d90 100644 --- a/internal/pkg/postgresGorm/helpers.go +++ b/internal/pkg/postgresgorm/helpers.go @@ -1,4 +1,4 @@ -package postgresGorm +package postgresgorm import ( "context" diff --git a/internal/pkg/postgresGorm/helpers/helpers.go b/internal/pkg/postgresgorm/helpers/helpers.go similarity index 71% rename from internal/pkg/postgresGorm/helpers/helpers.go rename to internal/pkg/postgresgorm/helpers/helpers.go index 1c487318..55afcf00 100644 --- a/internal/pkg/postgresGorm/helpers/helpers.go +++ b/internal/pkg/postgresgorm/helpers/helpers.go @@ -3,8 +3,8 @@ package helpers import ( "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/constants" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/constants" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/contracts" "emperror.dev/errors" "gorm.io/gorm" @@ -24,6 +24,20 @@ func GetTxFromContext(ctx context.Context) (*gorm.DB, error) { return tx, nil } +func GetTxFromContextIfExists(ctx context.Context) *gorm.DB { + gCtx, gCtxOk := ctx.(*contracts.GormContext) + if gCtxOk { + return gCtx.Tx + } + + tx, ok := ctx.Value(constants.TxKey).(*gorm.DB) + if !ok { + return nil + } + + return tx +} + func SetTxToContext(ctx context.Context, tx *gorm.DB) *contracts.GormContext { ctx = context.WithValue(ctx, constants.TxKey, tx) gormContext := &contracts.GormContext{Tx: tx, Context: ctx} diff --git a/internal/pkg/postgresGorm/mediatr/pipelines/mediator_transaction_pipeline.go b/internal/pkg/postgresgorm/mediatr/pipelines/mediator_transaction_pipeline.go similarity index 98% rename from internal/pkg/postgresGorm/mediatr/pipelines/mediator_transaction_pipeline.go rename to internal/pkg/postgresgorm/mediatr/pipelines/mediator_transaction_pipeline.go index fac0224a..b63a2d4a 100644 --- a/internal/pkg/postgresGorm/mediatr/pipelines/mediator_transaction_pipeline.go +++ b/internal/pkg/postgresgorm/mediatr/pipelines/mediator_transaction_pipeline.go @@ -5,7 +5,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/helpers" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/mehdihadeli/go-mediatr" diff --git a/internal/pkg/postgresGorm/repository/gorm_generic_repository.go b/internal/pkg/postgresgorm/repository/gorm_generic_repository.go similarity index 99% rename from internal/pkg/postgresGorm/repository/gorm_generic_repository.go rename to internal/pkg/postgresgorm/repository/gorm_generic_repository.go index b5a1cbe0..39bcf499 100644 --- a/internal/pkg/postgresGorm/repository/gorm_generic_repository.go +++ b/internal/pkg/postgresgorm/repository/gorm_generic_repository.go @@ -10,7 +10,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/data/specification" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" reflectionHelper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/reflectionhelper" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" diff --git a/internal/pkg/postgresGorm/repository/gorm_generic_repository_test.go b/internal/pkg/postgresgorm/repository/gorm_generic_repository_test.go similarity index 99% rename from internal/pkg/postgresGorm/repository/gorm_generic_repository_test.go rename to internal/pkg/postgresgorm/repository/gorm_generic_repository_test.go index b077348b..a723aa6e 100644 --- a/internal/pkg/postgresGorm/repository/gorm_generic_repository_test.go +++ b/internal/pkg/postgresgorm/repository/gorm_generic_repository_test.go @@ -9,7 +9,7 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" gorm2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/testcontainer/gorm" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" @@ -62,7 +62,7 @@ func (c *gormGenericRepositoryTest) SetupSuite() { PopulateContainerOptions(context.Background(), c.T()) c.Require().NoError(err) - gormDB, err := postgresGorm.NewGorm(opts) + gormDB, err := postgresgorm.NewGorm(opts) c.Require().NoError(err) c.DB = gormDB diff --git a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go b/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go index 1b4f37f4..3e4d0264 100644 --- a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go +++ b/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go @@ -3,8 +3,7 @@ package messagepersistence import ( "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/helpers" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" "gorm.io/gorm" ) @@ -13,26 +12,24 @@ type PostgresMessagePersistenceDBContextActionFunc func(ctx context.Context, mes type PostgresMessagePersistenceDBContext struct { *gorm.DB - logger logger.Logger } func NewPostgresMessagePersistenceDBContext( db *gorm.DB, - log logger.Logger, ) *PostgresMessagePersistenceDBContext { - c := &PostgresMessagePersistenceDBContext{DB: db, logger: log} + c := &PostgresMessagePersistenceDBContext{DB: db} return c } -// WithTx creates a transactional DBContext with getting tx-gorm from the ctx -func (c *PostgresMessagePersistenceDBContext) WithTx( +// WithTxIfExists creates a transactional DBContext with getting tx-gorm from the ctx. not throw an error if the transaction is not existing and returns an existing database. +func (c *PostgresMessagePersistenceDBContext) WithTxIfExists( ctx context.Context, -) (*PostgresMessagePersistenceDBContext, error) { - tx, err := helpers.GetTxFromContext(ctx) - if err != nil { - return nil, err +) *PostgresMessagePersistenceDBContext { + tx := helpers.GetTxFromContextIfExists(ctx) + if tx == nil { + return c } - return NewPostgresMessagePersistenceDBContext(tx, c.logger), nil + return NewPostgresMessagePersistenceDBContext(tx) } diff --git a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository.go b/internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository.go index 4b80314d..3735511a 100644 --- a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository.go +++ b/internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository.go @@ -2,34 +2,47 @@ package messagepersistence import ( "context" + "fmt" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/persistmessage" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "gorm.io/gorm" + uuid "github.com/satori/go.uuid" ) type postgresMessagePersistenceRepository struct { - db *gorm.DB - logger logger.Logger + messagingDBContext *PostgresMessagePersistenceDBContext + logger logger.Logger } func NewMessagePersistenceRepository( - db *gorm.DB, + postgresMessagePersistenceDBContext *PostgresMessagePersistenceDBContext, l logger.Logger, ) persistmessage.MessagePersistenceRepository { - return &postgresMessagePersistenceRepository{db: db, logger: l} + return &postgresMessagePersistenceRepository{ + messagingDBContext: postgresMessagePersistenceDBContext, + logger: l, + } } func (m *postgresMessagePersistenceRepository) Add( ctx context.Context, storeMessage *persistmessage.StoreMessage, ) error { - result := m.db.WithContext(ctx).Create(storeMessage) + dbContext := m.messagingDBContext.WithTxIfExists(ctx) + + // https://gorm.io/docs/create.html + result := dbContext.WithContext(ctx).Create(storeMessage) if result.Error != nil { - return result.Error + return customErrors.NewConflictErrorWrap( + result.Error, + "storeMessage already exists", + ) } + m.logger.Infof("Number of affected rows are: %d", result.RowsAffected) + return nil } @@ -37,51 +50,158 @@ func (m *postgresMessagePersistenceRepository) Update( ctx context.Context, storeMessage *persistmessage.StoreMessage, ) error { - // TODO implement me - panic("implement me") + dbContext := m.messagingDBContext.WithTxIfExists(ctx) + + // https://gorm.io/docs/update.html + result := dbContext.WithContext(ctx).Updates(storeMessage) + if result.Error != nil { + return customErrors.NewInternalServerErrorWrap( + result.Error, + "error in updating the storeMessage", + ) + } + + m.logger.Infof("Number of affected rows are: %d", result.RowsAffected) + + return nil } func (m *postgresMessagePersistenceRepository) ChangeState( ctx context.Context, - messageID string, + messageID uuid.UUID, status persistmessage.MessageStatus, ) error { - // TODO implement me - panic("implement me") + storeMessage, err := m.GetById(ctx, messageID) + if err != nil { + return customErrors.NewNotFoundErrorWrap( + err, + fmt.Sprintf( + "storeMessage with id `%s` not found in the database", + messageID.String(), + ), + ) + } + + storeMessage.MessageStatus = status + err = m.Update(ctx, storeMessage) + + return err } -func (m *postgresMessagePersistenceRepository) GetAll( +func (m *postgresMessagePersistenceRepository) GetAllActive( ctx context.Context, ) ([]*persistmessage.StoreMessage, error) { - // TODO implement me - panic("implement me") + var storeMessages []*persistmessage.StoreMessage + + predicate := func(sm *persistmessage.StoreMessage) bool { + return sm.MessageStatus == persistmessage.Stored + } + + dbContext := m.messagingDBContext.WithTxIfExists(ctx) + result := dbContext.WithContext(ctx).Where(predicate).Find(&storeMessages) + if result.Error != nil { + return nil, result.Error + } + + return storeMessages, nil } func (m *postgresMessagePersistenceRepository) GetByFilter( ctx context.Context, predicate func(*persistmessage.StoreMessage) bool, ) ([]*persistmessage.StoreMessage, error) { - // TODO implement me - panic("implement me") + var storeMessages []*persistmessage.StoreMessage + + dbContext := m.messagingDBContext.WithTxIfExists(ctx) + result := dbContext.WithContext(ctx).Where(predicate).Find(&storeMessages) + + if result.Error != nil { + return nil, result.Error + } + + return storeMessages, nil } func (m *postgresMessagePersistenceRepository) GetById( ctx context.Context, - id string, + id uuid.UUID, ) (*persistmessage.StoreMessage, error) { - // TODO implement me - panic("implement me") + var storeMessage *persistmessage.StoreMessage + + // https://gorm.io/docs/query.html#Retrieving-objects-with-primary-key + // https://gorm.io/docs/query.html#Struct-amp-Map-Conditions + // https://gorm.io/docs/query.html#Inline-Condition + // https://gorm.io/docs/advanced_query.html + result := m.messagingDBContext.WithContext(ctx). + Find(&storeMessage, id) + if result.Error != nil { + return nil, customErrors.NewNotFoundErrorWrap( + result.Error, + fmt.Sprintf( + "storeMessage with id `%s` not found in the database", + id.String(), + ), + ) + } + + m.logger.Infof("Number of affected rows are: %d", result.RowsAffected) + + return storeMessage, nil } func (m *postgresMessagePersistenceRepository) Remove( ctx context.Context, storeMessage *persistmessage.StoreMessage, ) (bool, error) { - // TODO implement me - panic("implement me") + id := storeMessage.ID + + storeMessage, err := m.GetById(ctx, id) + if err != nil { + return false, customErrors.NewNotFoundErrorWrap( + err, + fmt.Sprintf( + "storeMessage with id `%s` not found in the database", + id.String(), + ), + ) + } + + dbContext := m.messagingDBContext.WithTxIfExists(ctx) + + result := dbContext.WithContext(ctx).Delete(storeMessage, id) + if result.Error != nil { + return false, customErrors.NewInternalServerErrorWrap( + result.Error, + fmt.Sprintf( + "error in deleting storeMessage with id `%s` in the database", + id.String(), + ), + ) + } + + m.logger.Infof("Number of affected rows are: %d", result.RowsAffected) + + return true, nil } -func (m *postgresMessagePersistenceRepository) CleanupMessages() { - // TODO implement me - panic("implement me") +func (m *postgresMessagePersistenceRepository) CleanupMessages( + ctx context.Context, +) error { + predicate := func(sm *persistmessage.StoreMessage) bool { + return sm.MessageStatus == persistmessage.Processed + } + + dbContext := m.messagingDBContext.WithTxIfExists(ctx) + + result := dbContext.WithContext(ctx). + Where(predicate). + Delete(&persistmessage.StoreMessage{}) + + if result.Error != nil { + return result.Error + } + + m.logger.Infof("Number of affected rows are: %d", result.RowsAffected) + + return nil } diff --git a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository_test.go b/internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository_test.go new file mode 100644 index 00000000..16401686 --- /dev/null +++ b/internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository_test.go @@ -0,0 +1,159 @@ +package messagepersistence + +import ( + "context" + "testing" + "time" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/persistmessage" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" + gorm2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/testcontainer/gorm" + + uuid "github.com/satori/go.uuid" + "github.com/stretchr/testify/suite" + "gorm.io/gorm" +) + +type messagePersistenceRepositoryTest struct { + suite.Suite + DB *gorm.DB + logger logger.Logger + messagingRepository persistmessage.MessagePersistenceRepository + dbContext *PostgresMessagePersistenceDBContext + storeMessages []*persistmessage.StoreMessage + ctx context.Context +} + +func TestMessagePersistenceRepository(t *testing.T) { + suite.Run( + t, + &messagePersistenceRepositoryTest{logger: defaultLogger.GetLogger()}, + ) +} + +func (c *messagePersistenceRepositoryTest) SetupSuite() { + opts, err := gorm2.NewGormTestContainers(defaultLogger.GetLogger()). + PopulateContainerOptions(context.Background(), c.T()) + c.Require().NoError(err) + + gormDB, err := postgresgorm.NewGorm(opts) + c.Require().NoError(err) + c.DB = gormDB + + err = migrationDatabase(gormDB) + c.Require().NoError(err) + + c.dbContext = NewPostgresMessagePersistenceDBContext(gormDB) + c.messagingRepository = NewMessagePersistenceRepository( + c.dbContext, + defaultLogger.GetLogger(), + ) +} + +func (c *messagePersistenceRepositoryTest) SetupTest() { + ctx := context.Background() + c.ctx = ctx + p, err := seedData(context.Background(), c.DB) + c.Require().NoError(err) + c.storeMessages = p +} + +func (c *messagePersistenceRepositoryTest) TearDownTest() { + err := c.cleanupPostgresData() + c.Require().NoError(err) +} + +func (c *messagePersistenceRepositoryTest) BeginTx() { + c.logger.Info("starting transaction") + tx := c.dbContext.Begin() + gormContext := helpers.SetTxToContext(c.ctx, tx) + c.ctx = gormContext +} + +func (c *messagePersistenceRepositoryTest) CommitTx() { + tx := helpers.GetTxFromContextIfExists(c.ctx) + if tx != nil { + c.logger.Info("committing transaction") + tx.Commit() + } +} + +func (c *messagePersistenceRepositoryTest) Test_Add() { + message := &persistmessage.StoreMessage{ + ID: uuid.NewV4(), + MessageStatus: persistmessage.Processed, + Data: "test data 3", + DataType: "string", + Created: time.Now(), + DeliveryType: persistmessage.Outbox, + } + + c.BeginTx() + err := c.messagingRepository.Add(c.ctx, message) + c.CommitTx() + + c.Require().NoError(err) + + m, err := c.messagingRepository.GetById(c.ctx, message.ID) + if err != nil { + return + } + + c.Assert().NotNil(m) + c.Assert().Equal(message.ID, m.ID) +} + +func migrationDatabase(db *gorm.DB) error { + err := db.AutoMigrate(&persistmessage.StoreMessage{}) + if err != nil { + return err + } + + return nil +} + +func seedData( + ctx context.Context, + db *gorm.DB, +) ([]*persistmessage.StoreMessage, error) { + messages := []*persistmessage.StoreMessage{ + { + ID: uuid.NewV4(), + MessageStatus: persistmessage.Processed, + Data: "test data", + DataType: "string", + Created: time.Now(), + DeliveryType: persistmessage.Outbox, + }, + { + ID: uuid.NewV4(), + MessageStatus: persistmessage.Processed, + Data: "test data 2", + DataType: "string", + Created: time.Now(), + DeliveryType: persistmessage.Outbox, + }, + } + + err := db.WithContext(ctx).Create(messages).Error + if err != nil { + return nil, err + } + + return messages, nil +} + +func (c *messagePersistenceRepositoryTest) cleanupPostgresData() error { + tables := []string{"store_messages"} + // Iterate over the tables and delete all records + for _, table := range tables { + err := c.DB.Exec("DELETE FROM " + table).Error + + return err + } + + return nil +} diff --git a/internal/pkg/postgresmessaging/postgres_messaging_fx.go b/internal/pkg/postgresmessaging/postgres_messaging_fx.go new file mode 100644 index 00000000..16e50948 --- /dev/null +++ b/internal/pkg/postgresmessaging/postgres_messaging_fx.go @@ -0,0 +1,24 @@ +package postgresmessaging + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/persistmessage" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresmessaging/messagepersistence" + + "go.uber.org/fx" + "gorm.io/gorm" +) + +var Module = fx.Module( + "postgresmessagingfx", + fx.Provide( + messagepersistence.NewPostgresMessagePersistenceDBContext, + messagepersistence.NewMessagePersistenceRepository, + ), + fx.Invoke(migrateMessaging), +) + +func migrateMessaging(db *gorm.DB) error { + err := db.Migrator().AutoMigrate(&persistmessage.StoreMessage{}) + + return err +} diff --git a/internal/pkg/test/containers/contracts/gorm_container.go b/internal/pkg/test/containers/contracts/gorm_container.go index 93147041..82ea93ea 100644 --- a/internal/pkg/test/containers/contracts/gorm_container.go +++ b/internal/pkg/test/containers/contracts/gorm_container.go @@ -4,7 +4,7 @@ import ( "context" "testing" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" ) type PostgresContainerOptions struct { diff --git a/internal/pkg/test/containers/dockertest/gorm/gorm_container.go b/internal/pkg/test/containers/dockertest/gorm/gorm_container.go index 0dcf7696..69fa089a 100644 --- a/internal/pkg/test/containers/dockertest/gorm/gorm_container.go +++ b/internal/pkg/test/containers/dockertest/gorm/gorm_container.go @@ -6,7 +6,7 @@ import ( "strconv" "testing" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/contracts" "github.com/ory/dockertest/v3" diff --git a/internal/pkg/test/containers/dockertest/gorm/gorm_container_test.go b/internal/pkg/test/containers/dockertest/gorm/gorm_container_test.go index e6aeeb53..b5c7e424 100644 --- a/internal/pkg/test/containers/dockertest/gorm/gorm_container_test.go +++ b/internal/pkg/test/containers/dockertest/gorm/gorm_container_test.go @@ -9,7 +9,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" "github.com/stretchr/testify/assert" "go.uber.org/fx" diff --git a/internal/pkg/test/containers/dockertest/gorm/gorm_fx.go b/internal/pkg/test/containers/dockertest/gorm/gorm_fx.go index 6901f5b4..30527787 100644 --- a/internal/pkg/test/containers/dockertest/gorm/gorm_fx.go +++ b/internal/pkg/test/containers/dockertest/gorm/gorm_fx.go @@ -4,7 +4,7 @@ import ( "context" "testing" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" ) var GormDockerTestConatnerOptionsDecorator = func(t *testing.T, ctx context.Context) interface{} { diff --git a/internal/pkg/test/containers/gnomock/gorm/gorm_container.go b/internal/pkg/test/containers/gnomock/gorm/gorm_container.go index fb469815..c573b12d 100644 --- a/internal/pkg/test/containers/gnomock/gorm/gorm_container.go +++ b/internal/pkg/test/containers/gnomock/gorm/gorm_container.go @@ -5,7 +5,7 @@ import ( "log" "testing" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/contracts" "emperror.dev/errors" diff --git a/internal/pkg/test/containers/testcontainer/gorm/gorm_container.go b/internal/pkg/test/containers/testcontainer/gorm/gorm_container.go index 2cacd21c..b28bc5e0 100644 --- a/internal/pkg/test/containers/testcontainer/gorm/gorm_container.go +++ b/internal/pkg/test/containers/testcontainer/gorm/gorm_container.go @@ -7,7 +7,7 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/contracts" "emperror.dev/errors" diff --git a/internal/pkg/test/containers/testcontainer/gorm/gorm_container_test.go b/internal/pkg/test/containers/testcontainer/gorm/gorm_container_test.go index 17ef7d98..f7c4f563 100644 --- a/internal/pkg/test/containers/testcontainer/gorm/gorm_container_test.go +++ b/internal/pkg/test/containers/testcontainer/gorm/gorm_container_test.go @@ -10,7 +10,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" "github.com/docker/go-connections/nat" "github.com/stretchr/testify/assert" diff --git a/internal/pkg/test/containers/testcontainer/gorm/gorm_fx.go b/internal/pkg/test/containers/testcontainer/gorm/gorm_fx.go index 669e1ec7..95a51ea3 100644 --- a/internal/pkg/test/containers/testcontainer/gorm/gorm_fx.go +++ b/internal/pkg/test/containers/testcontainer/gorm/gorm_fx.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" ) var GormContainerOptionsDecorator = func(t *testing.T, ctx context.Context) interface{} { diff --git a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go b/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go index 38925055..7538d61b 100644 --- a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go +++ b/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go @@ -8,7 +8,7 @@ import ( metricspipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/mediatr/pipelines" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" tracingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/mediatr/pipelines" - postgrespipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/mediatr/pipelines" + postgrespipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/mediatr/pipelines" "github.com/mehdihadeli/go-mediatr" "gorm.io/gorm" diff --git a/internal/services/catalog_write_service/cmd/migration/main.go b/internal/services/catalog_write_service/cmd/migration/main.go index da9185a1..8f7d3a88 100644 --- a/internal/services/catalog_write_service/cmd/migration/main.go +++ b/internal/services/catalog_write_service/cmd/migration/main.go @@ -13,7 +13,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/goose" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" appconfig "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/config" "github.com/spf13/cobra" diff --git a/internal/services/catalog_write_service/internal/products/data/models/product_data_model.go b/internal/services/catalog_write_service/internal/products/data/models/product_data_model.go index e9972172..a11b22a0 100644 --- a/internal/services/catalog_write_service/internal/products/data/models/product_data_model.go +++ b/internal/services/catalog_write_service/internal/products/data/models/product_data_model.go @@ -5,6 +5,7 @@ import ( "github.com/goccy/go-json" uuid "github.com/satori/go.uuid" + "gorm.io/gorm" ) // https://gorm.io/docs/conventions.html @@ -12,6 +13,7 @@ import ( // ProductDataModel data model type ProductDataModel struct { + gorm.Model ProductId uuid.UUID `json:"productId" gorm:"primaryKey"` Name string `json:"name"` Description string `json:"description"` diff --git a/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go b/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go index 2ae1efdd..5c7462c7 100644 --- a/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go +++ b/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go @@ -9,7 +9,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" utils2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/utils" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/repository" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/repository" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" data2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" diff --git a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_handler.go b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_handler.go index 7a16da22..9f39d665 100644 --- a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_handler.go @@ -39,11 +39,6 @@ func (c *createProductHandler) Handle( ctx context.Context, command *CreateProduct, ) (*dtos.CreateProductResponseDto, error) { - dbContext, err := c.CatalogsDBContext.WithTx(ctx) - if err != nil { - return nil, err - } - product := &models.Product{ ProductId: command.ProductID, Name: command.Name, @@ -54,7 +49,7 @@ func (c *createProductHandler) Handle( var createProductResult *dtos.CreateProductResponseDto - result, err := dbContext.AddProduct(ctx, product) + result, err := c.CatalogsDBContext.AddProduct(ctx, product) if err != nil { return nil, err } diff --git a/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product_handler.go b/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product_handler.go index d9b8fef1..34ed91d6 100644 --- a/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product_handler.go @@ -40,12 +40,7 @@ func (c *deleteProductHandler) Handle( ctx context.Context, command *DeleteProduct, ) (*mediatr.Unit, error) { - dbContext, err := c.CatalogsDBContext.WithTx(ctx) - if err != nil { - return nil, err - } - - err = dbContext.DeleteProductByID(ctx, command.ProductID) + err := c.CatalogsDBContext.DeleteProductByID(ctx, command.ProductID) if err != nil { return nil, err } diff --git a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_handler.go b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_handler.go index 2aee6475..352498e6 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_handler.go @@ -5,7 +5,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" dtosv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" @@ -38,7 +38,7 @@ func (c *getProductsHandler) Handle( ctx context.Context, query *GetProducts, ) (*dtos.GetProductsResponseDto, error) { - products, err := postgresGorm.Paginate[*datamodel.ProductDataModel, *models.Product]( + products, err := postgresgorm.Paginate[*datamodel.ProductDataModel, *models.Product]( ctx, query.ListQuery, c.CatalogsDBContext.DB, diff --git a/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products_handler.go b/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products_handler.go index 2eef37bc..0547b99b 100644 --- a/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products_handler.go @@ -8,7 +8,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" reflectionHelper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/reflectionhelper" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" diff --git a/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_handler.go b/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_handler.go index 9911b4b5..3b02fcaa 100644 --- a/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_handler.go +++ b/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_handler.go @@ -44,12 +44,7 @@ func (c *updateProductHandler) Handle( ctx context.Context, command *UpdateProduct, ) (*mediatr.Unit, error) { - dbContext, err := c.CatalogsDBContext.WithTx(ctx) - if err != nil { - return nil, err - } - - product, err := dbContext.FindProductByID(ctx, command.ProductID) + product, err := c.CatalogsDBContext.FindProductByID(ctx, command.ProductID) if err != nil { return nil, customErrors.NewApplicationErrorWrapWithCode( err, @@ -66,7 +61,7 @@ func (c *updateProductHandler) Handle( product.Description = command.Description product.UpdatedAt = command.UpdatedAt - updatedProduct, err := dbContext.UpdateProduct(ctx, product) + updatedProduct, err := c.CatalogsDBContext.UpdateProduct(ctx, product) if err != nil { return nil, customErrors.NewApplicationErrorWrap( err, diff --git a/internal/services/catalog_write_service/internal/shared/app/test/test_app.go b/internal/services/catalog_write_service/internal/shared/app/test/test_app.go index d1d2a172..7e84e89f 100644 --- a/internal/services/catalog_write_service/internal/shared/app/test/test_app.go +++ b/internal/services/catalog_write_service/internal/shared/app/test/test_app.go @@ -11,7 +11,7 @@ import ( config3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" contracts2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/contracts" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/bus" config2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/testcontainer/gorm" diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go index 7e2b362c..29923b2e 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go +++ b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go @@ -8,7 +8,7 @@ import ( metricspipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/mediatr/pipelines" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" tracingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/mediatr/pipelines" - postgrespipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/mediatr/pipelines" + postgrespipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/mediatr/pipelines" "github.com/mehdihadeli/go-mediatr" "gorm.io/gorm" diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go index c259dffe..0d234de6 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go +++ b/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go @@ -8,7 +8,8 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/goose" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresmessaging" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" rabbitmq2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations/rabbitmq" @@ -25,7 +26,8 @@ var Module = fx.Module( core.Module, customEcho.Module, grpc.Module, - gormPostgres.Module, + postgresgorm.Module, + postgresmessaging.Module, goose.Module, rabbitmq.ModuleFunc( func() configurations.RabbitMQConfigurationBuilderFuc { diff --git a/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext.go b/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext.go index e2f7340e..1e29da56 100644 --- a/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext.go +++ b/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext.go @@ -7,7 +7,7 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/helpers" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" @@ -31,7 +31,7 @@ func NewCatalogsDBContext( return c } -// WithTx creates a transactional DBContext with getting tx-gorm from the ctx +// WithTx creates a transactional DBContext with getting tx-gorm from the ctx. This will throw an error if the transaction does not exist. func (c *CatalogsGormDBContext) WithTx( ctx context.Context, ) (*CatalogsGormDBContext, error) { @@ -43,6 +43,18 @@ func (c *CatalogsGormDBContext) WithTx( return NewCatalogsDBContext(tx, c.logger), nil } +// WithTxIfExists creates a transactional DBContext with getting tx-gorm from the ctx. not throw an error if the transaction is not existing and returns an existing database. +func (c *CatalogsGormDBContext) WithTxIfExists( + ctx context.Context, +) *CatalogsGormDBContext { + tx := helpers.GetTxFromContextIfExists(ctx) + if tx == nil { + return c + } + + return NewCatalogsDBContext(tx, c.logger) +} + func (c *CatalogsGormDBContext) RunInTx( ctx context.Context, action CatalogContextActionFunc, @@ -93,8 +105,12 @@ func (c *CatalogsGormDBContext) FindProductByID( ctx context.Context, id uuid.UUID, ) (*models.Product, error) { + var productDatas []*datamodel.ProductDataModel var productData *datamodel.ProductDataModel + s := c.DB.WithContext(ctx).Find(&productDatas).Error + fmt.Println(s) + // https://gorm.io/docs/query.html#Retrieving-objects-with-primary-key // https://gorm.io/docs/query.html#Struct-amp-Map-Conditions // https://gorm.io/docs/query.html#Inline-Condition @@ -123,11 +139,14 @@ func (c *CatalogsGormDBContext) FindProductByID( return product, nil } +// DeleteProductByID delete the product inner a tx if exists func (c *CatalogsGormDBContext) DeleteProductByID( ctx context.Context, id uuid.UUID, ) error { - product, err := c.FindProductByID(ctx, id) + dbContext := c.WithTxIfExists(ctx) + + product, err := dbContext.FindProductByID(ctx, id) if err != nil { return customErrors.NewNotFoundErrorWrap( err, @@ -146,7 +165,7 @@ func (c *CatalogsGormDBContext) DeleteProductByID( ) } - result := c.WithContext(ctx).Delete(productDataModel, id) + result := dbContext.WithContext(ctx).Delete(productDataModel, id) if result.Error != nil { return customErrors.NewInternalServerErrorWrap( result.Error, @@ -162,10 +181,13 @@ func (c *CatalogsGormDBContext) DeleteProductByID( return nil } +// AddProduct add the product inner a tx if exists func (c *CatalogsGormDBContext) AddProduct( ctx context.Context, product *models.Product, ) (*models.Product, error) { + dbContext := c.WithTxIfExists(ctx) + productDataModel, err := mapper.Map[*datamodel.ProductDataModel](product) if err != nil { return nil, customErrors.NewInternalServerErrorWrap( @@ -175,7 +197,7 @@ func (c *CatalogsGormDBContext) AddProduct( } // https://gorm.io/docs/create.html - result := c.WithContext(ctx).Create(productDataModel) + result := dbContext.WithContext(ctx).Create(productDataModel) if result.Error != nil { return nil, customErrors.NewConflictErrorWrap( result.Error, @@ -196,10 +218,13 @@ func (c *CatalogsGormDBContext) AddProduct( return product, err } +// UpdateProduct update the product inner a tx if exists func (c *CatalogsGormDBContext) UpdateProduct( ctx context.Context, product *models.Product, ) (*models.Product, error) { + dbContext := c.WithTxIfExists(ctx) + productDataModel, err := mapper.Map[*datamodel.ProductDataModel](product) if err != nil { return nil, customErrors.NewInternalServerErrorWrap( @@ -209,10 +234,10 @@ func (c *CatalogsGormDBContext) UpdateProduct( } // https://gorm.io/docs/update.html - result := c.WithContext(ctx).Updates(productDataModel) + result := dbContext.WithContext(ctx).Updates(productDataModel) if result.Error != nil { return nil, customErrors.NewInternalServerErrorWrap( - err, + result.Error, "error in updating the product", ) } diff --git a/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext_test.go b/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext_test.go index 61531ee4..350e6f9e 100644 --- a/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext_test.go +++ b/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext_test.go @@ -11,7 +11,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/goose" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations/mappings" datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" diff --git a/internal/services/catalog_write_service/internal/shared/testfixtures/integration/integration_test_fixture.go b/internal/services/catalog_write_service/internal/shared/testfixtures/integration/integration_test_fixture.go index 4208123f..c2f72913 100644 --- a/internal/services/catalog_write_service/internal/shared/testfixtures/integration/integration_test_fixture.go +++ b/internal/services/catalog_write_service/internal/shared/testfixtures/integration/integration_test_fixture.go @@ -8,7 +8,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/bus" fxcontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" config2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/testfixture" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" diff --git a/internal/services/catalog_write_service/internal/shared/testfixtures/unittest/unit_test_fixture.go b/internal/services/catalog_write_service/internal/shared/testfixtures/unittest/unit_test_fixture.go index a71c350b..32778f03 100644 --- a/internal/services/catalog_write_service/internal/shared/testfixtures/unittest/unit_test_fixture.go +++ b/internal/services/catalog_write_service/internal/shared/testfixtures/unittest/unit_test_fixture.go @@ -2,15 +2,19 @@ package unittest import ( "context" + "fmt" + "os" + "path/filepath" "testing" "time" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" mocks3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/mocks" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/gromlog" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresGorm/helpers" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations/mappings" datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" @@ -35,6 +39,8 @@ type UnitTestSharedFixture struct { Tracer trace.Tracer CatalogDBContext *dbcontext.CatalogsGormDBContext Ctx context.Context + projectRootDir string + dbFileName string } func NewUnitTestSharedFixture(t *testing.T) *UnitTestSharedFixture { @@ -47,9 +53,10 @@ func NewUnitTestSharedFixture(t *testing.T) *UnitTestSharedFixture { testTracer := nopetracer.Tracer("test_tracer") unit := &UnitTestSharedFixture{ - Cfg: cfg, - Log: log, - Tracer: testTracer, + Cfg: cfg, + Log: log, + Tracer: testTracer, + dbFileName: "sqlite.db", } return unit @@ -58,17 +65,18 @@ func NewUnitTestSharedFixture(t *testing.T) *UnitTestSharedFixture { // Shared Hooks func (c *UnitTestSharedFixture) SetupTest() { + ctx := context.Background() + c.Ctx = ctx + // create new mocks bus := &mocks3.Bus{} bus.On("PublishMessage", mock.Anything, mock.Anything, mock.Anything). Return(nil) - dbContext, products := c.createInMemoryDBContext() + dbContext, products := c.createSQLLiteDBContext() c.Bus = bus - ctx := context.Background() - c.Ctx = ctx c.CatalogDBContext = dbContext c.Products = products @@ -77,20 +85,24 @@ func (c *UnitTestSharedFixture) SetupTest() { } func (c *UnitTestSharedFixture) TearDownTest() { + err := c.dropSQLLiteDB() + c.Require().NoError(err) mapper.ClearMappings() } func (c *UnitTestSharedFixture) SetupSuite() { + environment.FixProjectRootWorkingDirectoryPath() + c.projectRootDir = environment.GetProjectRootWorkingDirectory() } func (c *UnitTestSharedFixture) TearDownSuite() { } -func (c *UnitTestSharedFixture) createInMemoryDBContext() (*dbcontext.CatalogsGormDBContext, []*datamodel.ProductDataModel) { - inMemoryGormDB, err := createInMemoryDB() +func (c *UnitTestSharedFixture) createSQLLiteDBContext() (*dbcontext.CatalogsGormDBContext, []*datamodel.ProductDataModel) { + sqlLiteGormDB, err := c.createSQLLiteDB() c.Require().NoError(err) - dbContext := dbcontext.NewCatalogsDBContext(inMemoryGormDB, c.Log) + dbContext := dbcontext.NewCatalogsDBContext(sqlLiteGormDB, c.Log) err = migrateGorm(dbContext) c.Require().NoError(err) @@ -106,26 +118,48 @@ func (c *UnitTestSharedFixture) BeginTx() { tx := c.CatalogDBContext.Begin() gormContext := helpers.SetTxToContext(c.Ctx, tx) c.Ctx = gormContext + + var productData []*datamodel.ProductDataModel + var productData2 []*datamodel.ProductDataModel + + s := c.CatalogDBContext.Find(&productData).Error + s2 := tx.Find(&productData2).Error + fmt.Println(s) + fmt.Println(s2) } func (c *UnitTestSharedFixture) CommitTx() { - tx, err := helpers.GetTxFromContext(c.Ctx) - c.Require().NoError(err) - c.Log.Info("committing transaction") - tx.Commit() + tx := helpers.GetTxFromContextIfExists(c.Ctx) + if tx != nil { + c.Log.Info("committing transaction") + tx.Commit() + } } -func createInMemoryDB() (*gorm.DB, error) { +func (c *UnitTestSharedFixture) createSQLLiteDB() (*gorm.DB, error) { + dbFilePath := filepath.Join(c.projectRootDir, c.dbFileName) + // https://gorm.io/docs/connecting_to_the_database.html#SQLite // https://github.com/glebarez/sqlite // https://www.connectionstrings.com/sqlite/ - db, err := gorm.Open( - sqlite.Open(":memory:"), + gormDB, err := gorm.Open( + sqlite.Open(dbFilePath), &gorm.Config{ Logger: gromlog.NewGormCustomLogger(defaultLogger.GetLogger()), }) - return db, err + return gormDB, err +} + +func (c *UnitTestSharedFixture) dropSQLLiteDB() error { + sqldb, _ := c.CatalogDBContext.DB.DB() + e := sqldb.Close() + c.Require().NoError(e) + + dbFilePath := filepath.Join(c.projectRootDir, c.dbFileName) + err := os.Remove(dbFilePath) + + return err } func migrateGorm(dbContext *dbcontext.CatalogsGormDBContext) error { diff --git a/internal/services/catalog_write_service/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go b/internal/services/catalog_write_service/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go index 9daa5f84..a2cd30f6 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go +++ b/internal/services/catalog_write_service/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go @@ -64,12 +64,11 @@ func (c *createProductHandlerUnitTests) Test_Handle_Should_Create_New_Product_Wi } c.BeginTx() - _, err := c.handler.Handle(c.Ctx, createProduct) - c.Require().NoError(err) - c.CommitTx() + c.Require().NoError(err) + c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 1) res, err := c.CatalogDBContext.FindProductByID(c.Ctx, id) From e0ec597474a27dee55b35e7d7e9226d29a6b8306 Mon Sep 17 00:00:00 2001 From: Mehdi Hadeli Date: Mon, 18 Dec 2023 01:21:51 +0330 Subject: [PATCH 10/15] feat: :sparkles: supporting Inbox and Outbox Pattern #70 --- Makefile | 93 +++--- .../docs.go | 2 +- .../swagger.json | 0 .../swagger.yaml | 0 .../docs.go | 2 +- .../swagger.json | 0 .../swagger.yaml | 0 .../{order_service => orderservice}/docs.go | 2 +- .../swagger.json | 0 .../swagger.yaml | 0 .../products.proto | 0 .../orders.proto | 0 .../docker-compose.infrastructure.yaml | 292 +++++++++--------- .../docker-compose/monitoring/prometheus.yml | 2 +- deployments/docker-compose/traefik.yaml | 4 +- internal/pkg/core/core_fx.go | 8 +- internal/pkg/core/customtypes/custom_time.go | 2 +- internal/pkg/core/events/event.go | 14 +- internal/pkg/core/messaging/mocks/IMessage.go | 9 +- .../otel/tracing/producer/producer.go | 2 +- .../message_persistence_service.go | 24 -- ...tence_repository.go => message_service.go} | 14 +- .../messaging/persistmessage/store_message.go | 4 +- internal/pkg/core/messaging/types/message.go | 23 +- .../messaging/types/mock_IMessage_test.go | 9 +- internal/pkg/core/mocks/EventSerializer.go | 17 +- internal/pkg/core/mocks/IDomainEvent.go | 7 +- internal/pkg/core/mocks/IEvent.go | 7 +- .../serializer/contratcs/event_serializer.go | 17 + .../contratcs/event_serrialization_result.go | 6 + .../contratcs/message_serializer.go | 16 + .../contratcs/metadata_serializer.go | 8 + .../serializer/{ => contratcs}/serilizer.go | 2 +- .../pkg/core/serializer/event_serializer.go | 154 --------- .../core/serializer/json/event_serializer.go | 134 ++++++++ .../core/serializer/json/json_serializer.go | 4 +- .../serializer/json/json_serilizer_test.go | 5 +- .../serializer/json/message_serializer.go | 1 + .../serializer/json/metadata_serializer.go | 44 +++ .../core/serializer/metadata_serializer.go | 48 --- internal/pkg/es/errors/errors.go | 2 +- .../errors/aggregate_not_found_error.go | 2 +- .../errors/append_to_stream_error.go | 2 +- .../errors/delete_stream_error.go | 2 +- .../eventstroredb/errors/read_stream_error.go | 2 +- .../errors/stream_not_found_error.go | 2 +- .../errors/truncate_stream_error.go | 2 +- internal/pkg/eventstroredb/esdb_serilizer.go | 64 +++- ...sdb_subscription_check_point_repository.go | 2 +- internal/pkg/eventstroredb/event_store.go | 24 +- .../custom_grpc_errors.go | 2 +- .../grpc_error_parser.go | 6 +- .../{grpcErrors => grpcerrors}/grpc_errors.go | 2 +- .../error_interceptor.go | 10 +- internal/pkg/grpc/server.go | 2 +- internal/pkg/health/health_endpoint.go | 2 +- .../config/echo_http_options.go | 0 .../contracts/echoserver.go | 2 +- .../contracts/route_builder.go | 0 .../custom_echo_fx.go | 4 +- .../echo_server.go | 16 +- .../hadnlers/problemdetail_error_handler.go | 2 +- .../middlewares/ip_ratelimit/config.go | 0 .../middlewares/ip_ratelimit/ip_ratelimit.go | 0 .../middlewares/log/config.go | 0 .../middlewares/log/log_middleware.go | 0 .../middlewares/otel_metrics/config.go | 0 .../middlewares/otel_metrics/metric.go | 0 .../otel_metrics/metrics_middleware.go | 0 .../middlewares/otel_metrics/view.go | 0 .../middlewares/otel_tracing/config.go | 0 .../otel_tracing/tracing_middleware.go | 0 .../middlewares/problem_detail/config.go | 2 +- .../problem_detail_middleware.go | 2 +- internal/pkg/http/http_fx.go | 2 +- .../contracts/contracts.go | 0 .../customerrors}/api_error.go | 0 .../customerrors}/application_error.go | 0 .../customerrors}/bad_request_error.go | 0 .../customerrors}/conflict_error.go | 0 .../customerrors}/custom_errors.go | 2 +- .../customerrors}/custom_errors_test.go | 4 +- .../customerrors}/domain_error.go | 0 .../customerrors}/forbiden_error.go | 0 .../customerrors}/internal_server_error.go | 0 .../customerrors}/marshaling_error.go | 0 .../customerrors}/not_found_error.go | 0 .../customerrors}/unauthorized_error.go | 0 .../customerrors}/unmarshaling_error.go | 0 .../customerrors}/validation_error.go | 0 .../custom_problem_details_errors.go | 0 .../problemdetails}/option_builder.go | 0 .../problemdetails}/problem_detail_parser.go | 4 +- .../problemdetails}/problem_details.go | 2 +- .../problemdetails}/problem_details_test.go | 2 +- .../repository/mongo_generic_repository.go | 2 +- .../mongo_generic_repository_test.go | 2 +- internal/pkg/otel/metrics/metrics.go | 2 +- internal/pkg/otel/metrics/metrics_fx.go | 2 +- internal/pkg/otel/metrics/metrics_test.go | 2 +- internal/pkg/otel/tracing/utils/utils.go | 9 +- internal/pkg/postgresgorm/db.go | 28 +- internal/pkg/postgresgorm/gorm_options.go | 13 + internal/pkg/postgresgorm/helpers.go | 70 ----- internal/pkg/postgresgorm/helpers/helpers.go | 32 +- .../repository/gorm_generic_repository.go | 4 +- .../gorm_generic_repository_test.go | 2 +- internal/pkg/postgresgorm/scopes/scopes.go | 88 ++++++ .../message_persistence_dbcontext.go | 12 + ...ository.go => postgres_message_service.go} | 96 +++++- ...st.go => postgres_message_service_test.go} | 24 +- .../postgres_messaging_fx.go | 2 +- .../pkg/rabbitmq/bus/rabbitmq_bus_test.go | 57 +++- .../rabbitmq/consumer/rabbitmq_consumer.go | 86 +++--- .../consumer/rabbitmq_consumer_test.go | 5 +- .../rabbitmq/producer/rabbitmq_producer.go | 33 +- .../producer/rabbitmq_producer_test.go | 22 +- internal/pkg/rabbitmq/rabbitmq_fx.go | 5 +- internal/pkg/rabbitmq/types/connection.go | 2 +- .../pkg/reflection/typemapper/type_mapper.go | 12 +- .../reflection/typemapper/type_mapper_test.go | 2 +- .../{error_utils => errorutils}/errors.go | 2 +- .../errors_test.go | 0 internal/services/catalog_read_service/.env | 1 - internal/services/catalog_write_service/.env | 1 - .../.air.toml | 0 .../.dockerignore | 0 internal/services/catalogreadservice/.env | 1 + .../.gitignore | 0 .../.golangci.yml | 0 .../Dockerfile | 0 .../Makefile | 0 .../arch-go.yml | 0 .../client.http | 0 .../cmd/app/main.go | 0 .../cmd/migration/.gitkeep | 0 .../config/config.development.json | 6 +- .../config/config.go | 0 .../config/config.test.json | 6 +- .../config/confix_fx.go | 0 .../docs/docs.go | 0 .../docs/swagger.json | 0 .../docs/swagger.yaml | 0 .../go.mod | 18 +- .../go.sum | 115 ++----- .../mappings/mapping_profile.go | 0 .../mediator/mediator_configurations.go | 0 .../products_module_configurator.go | 0 .../rabbitmq/rabbitmq_configuration.go | 0 .../internal/products/consts/consts.go | 0 .../data/product_cache_repository.go | 0 .../contracts/data/product_repository.go | 0 .../contracts/params/product_route_params.go | 0 .../repositories/mongo_product_repository.go | 0 .../repositories/redis_product_repository.go | 0 .../internal/products/dto/product_dto.go | 0 .../creating_product/v1/create_product.go | 0 .../v1/create_product_handler.go | 2 +- .../v1/dtos/create_product_response_dto.go | 0 .../externalevents/product_created.go | 0 .../product_created_consumer.go | 2 +- .../v1/commands/delete_product.go | 0 .../v1/commands/delete_product_handler.go | 2 +- .../external_events/product_deleted.go | 0 .../product_deleted_consumer.go | 2 +- .../v1/dtos/get_product_by_id_request_dto.go | 0 .../v1/dtos/get_product_by_id_response_dto.go | 0 .../endpoints/get_product_by_id_endpoint.go | 2 +- .../v1/queries/get_product_by_id.go | 0 .../v1/queries/get_product_by_id_handler.go | 2 +- .../v1/dtos/get_products_request_dto.go | 0 .../v1/dtos/get_products_response_dto.go | 0 .../v1/endpoints/get_products_endpoint.go | 2 +- .../v1/queries/get_products.go | 0 .../v1/queries/get_products_handler.go | 2 +- .../v1/dtos/search_products_request_dto.go | 0 .../v1/dtos/search_products_response_dto.go | 0 .../v1/endpoints/search_products_endpoint.go | 2 +- .../v1/queries/search_products.go | 0 .../v1/queries/search_products_handler.go | 2 +- .../v1/commands/update_product.go | 0 .../v1/commands/update_product_handler.go | 2 +- .../external_events/product_updated.go | 0 .../product_updated_consumer.go | 2 +- .../internal/products/models/product.go | 0 .../internal/products/products_fx.go | 2 +- .../internal/shared/app/app.go | 0 .../internal/shared/app/application.go | 0 .../shared/app/application_builder.go | 0 .../internal/shared/app/test/test_app.go | 2 +- .../shared/app/test/test_application.go | 0 .../app/test/test_application_builder.go | 0 .../catalogs/catalogs_configurator.go | 2 +- .../catalogs/catalogs_configurator_swagger.go | 2 +- .../configurations/catalogs/catalogs_fx.go | 0 .../infrastructure_configurator.go | 0 .../infrastructure/infrastructure_fx.go | 2 +- .../shared/contracts/catalogs_metrics.go | 0 .../integration/integration_test_fixture.go | 0 .../mocks/ProductCacheRepository.go | 0 .../mocks/ProductRepository.go | 0 .../mocks/UnsafeProductsServiceServer.go | 0 .../readme.md | 0 .../revive-config.toml | 0 .../staticcheck.conf | 0 .../taskfile.yml | 0 .../taskfile_db.yml | 0 .../taskfile_test.yml | 0 .../v1/get_product_by_id_test.go | 0 .../v1/get_products_endpoint_test.go | 0 .../data/mongo_product_repository_test.go | 2 +- .../v1/commands/create_product_test.go | 0 .../v1/events/product_created_test.go | 0 .../v1/commands/delete_product_test.go | 0 .../v1/events/product_deleted_test.go | 0 .../v1/queries/get_product_by_id_test.go | 0 .../v1/queries/get_products_handler_test.go | 0 .../commands/update_product_handler_test.go | 0 .../v1/events/product_updated_test.go | 0 .../test/load_tests/.openapi-generator-ignore | 0 .../test/load_tests/.openapi-generator/FILES | 0 .../load_tests/.openapi-generator/VERSION | 0 .../test/load_tests/README.md | 0 .../test/load_tests/script.js | 0 .../.air.toml | 0 .../.dockerignore | 0 internal/services/catalogwriteservice/.env | 1 + .../.gitignore | 0 .../.golangci.yml | 0 .../Dockerfile | 0 .../Makefile | 0 .../arch-go.yml | 0 .../atlas.hcl | 0 .../client.http | 0 .../cmd/app/main.go | 0 .../cmd/migration/main.go | 0 .../config/app_options.go | 0 .../config/config.development.json | 6 +- .../config/config.test.json | 6 +- .../config/config_fx.go | 0 .../db/fixtures/products/products.yaml | 0 .../db/migrations/atlas/20230919170700.sql | 0 .../db/migrations/atlas/atlas.sum | 0 .../goose/00001_enable_uuid_extension.sql | 0 .../goose/00002_create_products_table.sql | 0 .../db/migrations/atlas/goose/atlas.sum | 0 .../db/migrations/atlas/readme.md | 0 .../000001_enable_uuid_extension.down.sql | 0 .../000001_enable_uuid_extension.up.sql | 0 .../000002_create_products_table.down.sql | 0 .../000002_create_products_table.up.sql | 0 .../db/migrations/go-migrate/atlas.sum | 0 .../db/migrations/go-migrate/readme.md | 0 .../db/migrations/go-migrate/schema.sql | 0 .../00001_enable_uuid_extension.sql | 0 .../00002_create_products_table.sql | 0 .../db/migrations/goose-migrate/readme.md | 0 .../docs/docs.go | 0 .../docs/swagger.json | 0 .../docs/swagger.yaml | 0 .../go.mod | 0 .../go.sum | 0 .../configurations/endpoints/endpoints.go | 0 .../mappings/mapping_profile.go | 2 +- .../configurations/mediator/mediator.go | 0 .../products_module_configurator.go | 0 .../rabbitmq/rabbitmq_configurations.go | 0 .../products/contracts/product_repository.go | 0 .../data/models/product_data_model.go | 18 +- .../repositories/pg_product_repository.go | 18 +- .../v1/fxparams/product_handler_params.go | 0 .../dtos/v1/fxparams/product_route_params.go | 0 .../internal/products/dtos/v1/product_dto.go | 0 .../creatingproduct/v1/create_product.go | 0 .../v1/create_product_endpoint.go | 2 +- .../v1/create_product_handler.go | 8 +- .../v1/dtos/create_product_request_dto.go | 0 .../v1/dtos/create_product_response_dto.go | 0 .../v1/events/domainevents/.gitkeep | 0 .../integrationevents/product_created.go | 0 .../deletingproduct/v1/delete_product.go | 0 .../v1/delete_product_endpoint.go | 2 +- .../v1/delete_product_handler.go | 4 +- .../v1/dtos/delete_product_request_dto.go | 0 .../integrationevents/product_deleted.go | 0 .../v1/dtos/get_product_by_id_request_dto.go | 0 .../v1/dtos/get_product_by_id_response_dto.go | 0 .../v1/get_product_by_id.go | 0 .../v1/get_product_by_id_endpoint.go | 2 +- .../v1/get_product_by_id_handler.go | 4 +- .../v1/dtos/get_products_request_dto.go | 0 .../v1/dtos/get_products_response_dto.go | 0 .../gettingproducts}/v1/get_products.go | 0 .../v1/get_products_endpoint.go | 4 +- .../v1/get_products_handler.go | 8 +- .../v1/dtos/search_products_request_dto.go | 0 .../v1/dtos/search_products_response_dto.go | 0 .../searchingproduct/v1/search_products.go | 0 .../v1/search_products_endpoint.go | 2 +- .../v1/search_products_handler.go | 4 +- .../v1/dtos/update_product_request_dto.go | 0 .../integrationevents/product_updated.go | 0 .../updatingproduct/v1/update_product.go | 0 .../v1/update_product_endpoint.go | 2 +- .../v1/update_product_handler.go | 4 +- .../internal/products/models/product.go | 2 +- .../internal/products/products_fx.go | 4 +- .../internal/shared/app/app.go | 0 .../internal/shared/app/application.go | 0 .../shared/app/application_builder.go | 0 .../internal/shared/app/test/test_app.go | 6 +- .../shared/app/test/test_application.go | 0 .../app/test/test_application_builder.go | 0 .../catalogs/catalogs_configurator.go | 14 +- .../catalogs_configurator_migration.go | 23 +- .../catalogs/catalogs_configurator_seed.go | 104 +++++++ .../catalogs/catalogs_configurator_swagger.go | 2 +- .../configurations/catalogs/catalogs_fx.go | 0 .../infrastructure_configurator.go | 0 .../infrastructure/infrastructure_fx.go | 2 +- .../shared/contracts/catalogs_metrics.go | 0 .../internal/shared/data/data_fx.go | 0 .../data/dbcontext/catalogs_dbcontext.go | 48 +-- .../data/dbcontext/catalogs_dbcontext_test.go | 124 ++++++-- .../internal/shared/data/scopes/scopes.go | 3 + .../shared/grpc/genproto/products.pb.go | 39 +-- .../shared/grpc/genproto/products_grpc.pb.go | 4 +- .../grpc/product_grpc_service_server.go | 8 +- .../integration/integration_test_fixture.go | 24 +- .../unittest/unit_test_fixture.go | 142 +++++---- .../mocks/CatalogContext.go | 0 .../mocks/ProductRepository.go | 0 .../mocks/ProductsServiceClient.go | 0 .../mocks/ProductsServiceServer.go | 0 .../mocks/UnsafeProductsServiceServer.go | 0 .../readme.md | 0 .../revive-config.toml | 0 .../taskfile.yml | 0 .../taskfile_db.yml | 0 .../taskfile_test.yml | 0 .../creatingproduct/v1/create_product_test.go | 0 .../deletingproduct/v1/delete_product_test.go | 2 +- .../v1/get_product_by_id_test.go | 2 +- .../gettingproducts/v1/get_products_test.go | 0 .../v1/search_products_test.go | 0 .../updatingproduct/v1/update_product_test.go | 2 +- .../grpc/product_grpc_service_server_test.go | 6 +- .../pg_product_repository_integration_test.go | 18 +- .../catalogs_unit_of_work_integration_test.go | 10 +- .../creatingproduct/v1/create_product_test.go | 4 +- .../deletingproduct/v1/delete_product_test.go | 4 +- .../v1/get_product_by_id_test.go | 4 +- .../gettingproducts/v1/get_products_test.go | 4 +- .../updatingproduct/v1/update_product_test.go | 12 +- .../test/load/.openapi-generator-ignore | 0 .../test/load/.openapi-generator/FILES | 0 .../test/load/.openapi-generator/VERSION | 0 .../test/load/README.md | 0 .../test/load/script.js | 0 .../v1/create_product_handler_unit_test.go | 4 +- .../v1/create_product_unit_test.go | 0 .../v1/delete_product_handler_unit_test.go | 6 +- .../v1/delete_product_unit_test.go | 0 .../v1/get_product_by_Id_unit_test.go | 0 .../v1/get_product_by_id_handler_unit_test.go | 8 +- .../v1/get_products_handler_unit_test.go | 6 +- .../v1/search_products_unit_test.go | 2 +- .../v1/update_product_handler_unit_test.go | 12 +- .../v1/update_product_unit_test.go | 0 .../unit/products/mappings_profile_test.go | 6 +- internal/services/order_service/.env | 1 - .../{order_service => orderservice}/.air.toml | 0 .../.dockerignore | 0 internal/services/orderservice/.env | 1 + .../.golangci.yml | 0 .../Dockerfile | 0 .../{order_service => orderservice}/Makefile | 0 .../arch-go.yml | 0 .../client.http | 0 .../cmd/app/main.go | 0 .../cmd/migration/.gitkeep | 0 .../config/config.development.json | 6 +- .../config/config.go | 0 .../config/config.test.json | 6 +- .../config/config_fx.go | 0 .../docs/docs.go | 0 .../docs/swagger.json | 0 .../docs/swagger.yaml | 0 .../{order_service => orderservice}/go.mod | 15 +- .../{order_service => orderservice}/go.sum | 41 ++- .../mappings/mappings_profile.go | 0 .../mediatr/mediator_configurations.go | 0 .../orders_module_configurator.go | 2 +- .../rabbitmq/rabbitmq_configurations.go | 0 .../params/order_projection_params.go | 0 .../contracts/params/order_route_params.go | 0 .../repositories/order_repository.go | 0 .../elastic_order_read_repository.go | 0 .../mongo_order_read_repository.go | 0 .../internal/orders/dtos/v1/order_dto.go | 0 .../internal/orders/dtos/v1/order_read_dto.go | 0 .../internal/orders/dtos/v1/shopItem_dto.go | 0 .../orders/dtos/v1/shopItem_read_dto.go | 0 .../invalid_delivery_address_error.go | 2 +- .../domain_exceptions/invalid_email_error.go | 2 +- .../order_domain_errors_test.go | 4 +- .../order_items_required_errors.go | 2 +- .../order_not_found_error.go | 2 +- .../v1/commands/create_order.go | 0 .../v1/commands/create_order_handler.go | 2 +- .../v1/dtos/create_order_request_dto.go | 0 .../v1/dtos/create_order_response_dto.go | 0 .../v1/endpoints/create_order_endpoint.go | 2 +- .../v1/events/domain_events/order_created.go | 2 +- .../integration_events/order_created.go | 0 .../v1/dtos/get_order_by_id_request_dto.go | 0 .../v1/dtos/get_order_by_id_response_dto.go | 0 .../v1/endpoints/get_order_by_id_endpoint.go | 2 +- .../v1/queries/get_order_by_id.go | 0 .../v1/queries/get_order_by_id_handler.go | 2 +- .../v1/dtos/get_orders_request_dto.go | 0 .../v1/dtos/get_orders_response_dto.go | 0 .../v1/endpoints/get_orders_endpoint.go | 2 +- .../getting_orders/v1/queries/get_orders.go | 0 .../v1/queries/get_orders_handler.go | 2 +- .../v1/commands/submit_order.go | 0 .../events/domain_events/order_submitted.go | 2 +- .../v1/commands/update_shopping_card.go | 0 .../v1/events/shopping_card_updated.go | 0 .../orders/models/orders/aggregate/order.go | 2 +- .../models/orders/read_models/order_read.go | 0 .../orders/read_models/shop_item_read.go | 0 .../models/orders/value_objects/shop_item.go | 0 .../internal/orders/orders_fx.go | 2 +- .../projections/elastic_order_projection.go | 0 .../projections/mongo_order_projection.go | 2 +- .../internal/shared/app/app.go | 0 .../internal/shared/app/application.go | 0 .../shared/app/application_builder.go | 0 .../internal/shared/app/test/test_app.go | 2 +- .../shared/app/test/test_application.go | 0 .../app/test/test_application_builder.go | 0 .../infrastructure_configurator.go | 0 .../infrastructure/infrastructure_fx.go | 2 +- .../orders/orders_configurator.go | 2 +- .../orders/orders_configurator_swagger.go | 2 +- .../shared/configurations/orders/orders_fx.go | 0 .../shared/contracts/orders_metrics.go | 0 .../shared/grpc/genproto/orders.pb.go | 2 +- .../shared/grpc/genproto/orders_grpc.pb.go | 4 +- .../shared/grpc/order_grpc_service_server.go | 2 +- .../integration/integration_test_fixture.go | 0 .../mocks/InvalidDeliveryAddressError.go | 0 .../mocks/InvalidEmailAddressError.go | 0 .../mocks/OrderElasticRepository.go | 0 .../mocks/OrderMongoRepository.go | 0 .../mocks/OrderNotFoundError.go | 0 .../mocks/OrderShopItemsRequiredError.go | 0 .../mocks/OrdersServiceClient.go | 0 .../mocks/OrdersServiceServer.go | 0 .../mocks/UnsafeOrdersServiceServer.go | 0 .../mocks/orderReadRepository.go | 0 .../{order_service => orderservice}/readme.md | 0 .../revive-config.toml | 0 .../taskfile.yml | 0 .../taskfile_db.yml | 0 .../taskfile_test.yml | 0 .../creating_order/v1/create_order_test.go | 0 .../v1/get_order_by_id_test.go | 0 .../grpc/order_grpc_service_server_test.go | 0 .../creating_order/v1/create_order_test.go | 0 .../v1/get_order_by_id_test.go | 0 taskfile.yml | 64 ++-- 473 files changed, 1635 insertions(+), 1257 deletions(-) rename api/openapi/{catalog_read_service => catalogreadservice}/docs.go (99%) rename api/openapi/{catalog_read_service => catalogreadservice}/swagger.json (100%) rename api/openapi/{catalog_read_service => catalogreadservice}/swagger.yaml (100%) rename api/openapi/{catalog_write_service => catalogwriteservice}/docs.go (99%) rename api/openapi/{catalog_write_service => catalogwriteservice}/swagger.json (100%) rename api/openapi/{catalog_write_service => catalogwriteservice}/swagger.yaml (100%) rename api/openapi/{order_service => orderservice}/docs.go (99%) rename api/openapi/{order_service => orderservice}/swagger.json (100%) rename api/openapi/{order_service => orderservice}/swagger.yaml (100%) rename api/protobuf/{catalog_write_service => catalogwriteservice}/products.proto (100%) rename api/protobuf/{order_service => orderservice}/orders.proto (100%) delete mode 100644 internal/pkg/core/messaging/persistmessage/message_persistence_service.go rename internal/pkg/core/messaging/persistmessage/{message_persistence_repository.go => message_service.go} (61%) create mode 100644 internal/pkg/core/serializer/contratcs/event_serializer.go create mode 100644 internal/pkg/core/serializer/contratcs/event_serrialization_result.go create mode 100644 internal/pkg/core/serializer/contratcs/message_serializer.go create mode 100644 internal/pkg/core/serializer/contratcs/metadata_serializer.go rename internal/pkg/core/serializer/{ => contratcs}/serilizer.go (95%) delete mode 100644 internal/pkg/core/serializer/event_serializer.go create mode 100644 internal/pkg/core/serializer/json/event_serializer.go create mode 100644 internal/pkg/core/serializer/json/message_serializer.go create mode 100644 internal/pkg/core/serializer/json/metadata_serializer.go delete mode 100644 internal/pkg/core/serializer/metadata_serializer.go rename internal/pkg/grpc/{grpcErrors => grpcerrors}/custom_grpc_errors.go (99%) rename internal/pkg/grpc/{grpcErrors => grpcerrors}/grpc_error_parser.go (96%) rename internal/pkg/grpc/{grpcErrors => grpcerrors}/grpc_errors.go (99%) rename internal/pkg/grpc/interceptors/{grpc_error => grpcerror}/error_interceptor.go (87%) rename internal/pkg/http/{custom_echo => customecho}/config/echo_http_options.go (100%) rename internal/pkg/http/{custom_echo => customecho}/contracts/echoserver.go (96%) rename internal/pkg/http/{custom_echo => customecho}/contracts/route_builder.go (100%) rename internal/pkg/http/{custom_echo => customecho}/custom_echo_fx.go (98%) rename internal/pkg/http/{custom_echo => customecho}/echo_server.go (92%) rename internal/pkg/http/{custom_echo => customecho}/hadnlers/problemdetail_error_handler.go (86%) rename internal/pkg/http/{custom_echo => customecho}/middlewares/ip_ratelimit/config.go (100%) rename internal/pkg/http/{custom_echo => customecho}/middlewares/ip_ratelimit/ip_ratelimit.go (100%) rename internal/pkg/http/{custom_echo => customecho}/middlewares/log/config.go (100%) rename internal/pkg/http/{custom_echo => customecho}/middlewares/log/log_middleware.go (100%) rename internal/pkg/http/{custom_echo => customecho}/middlewares/otel_metrics/config.go (100%) rename internal/pkg/http/{custom_echo => customecho}/middlewares/otel_metrics/metric.go (100%) rename internal/pkg/http/{custom_echo => customecho}/middlewares/otel_metrics/metrics_middleware.go (100%) rename internal/pkg/http/{custom_echo => customecho}/middlewares/otel_metrics/view.go (100%) rename internal/pkg/http/{custom_echo => customecho}/middlewares/otel_tracing/config.go (100%) rename internal/pkg/http/{custom_echo => customecho}/middlewares/otel_tracing/tracing_middleware.go (100%) rename internal/pkg/http/{custom_echo => customecho}/middlewares/problem_detail/config.go (83%) rename internal/pkg/http/{custom_echo => customecho}/middlewares/problem_detail/problem_detail_middleware.go (89%) rename internal/pkg/http/{http_errors => httperrors}/contracts/contracts.go (100%) rename internal/pkg/http/{http_errors/custom_errors => httperrors/customerrors}/api_error.go (100%) rename internal/pkg/http/{http_errors/custom_errors => httperrors/customerrors}/application_error.go (100%) rename internal/pkg/http/{http_errors/custom_errors => httperrors/customerrors}/bad_request_error.go (100%) rename internal/pkg/http/{http_errors/custom_errors => httperrors/customerrors}/conflict_error.go (100%) rename internal/pkg/http/{http_errors/custom_errors => httperrors/customerrors}/custom_errors.go (98%) rename internal/pkg/http/{http_errors/custom_errors => httperrors/customerrors}/custom_errors_test.go (99%) rename internal/pkg/http/{http_errors/custom_errors => httperrors/customerrors}/domain_error.go (100%) rename internal/pkg/http/{http_errors/custom_errors => httperrors/customerrors}/forbiden_error.go (100%) rename internal/pkg/http/{http_errors/custom_errors => httperrors/customerrors}/internal_server_error.go (100%) rename internal/pkg/http/{http_errors/custom_errors => httperrors/customerrors}/marshaling_error.go (100%) rename internal/pkg/http/{http_errors/custom_errors => httperrors/customerrors}/not_found_error.go (100%) rename internal/pkg/http/{http_errors/custom_errors => httperrors/customerrors}/unauthorized_error.go (100%) rename internal/pkg/http/{http_errors/custom_errors => httperrors/customerrors}/unmarshaling_error.go (100%) rename internal/pkg/http/{http_errors/custom_errors => httperrors/customerrors}/validation_error.go (100%) rename internal/pkg/http/{http_errors/problemDetails => httperrors/problemdetails}/custom_problem_details_errors.go (100%) rename internal/pkg/http/{http_errors/problemDetails => httperrors/problemdetails}/option_builder.go (100%) rename internal/pkg/http/{http_errors/problemDetails => httperrors/problemdetails}/problem_detail_parser.go (97%) rename internal/pkg/http/{http_errors/problemDetails => httperrors/problemdetails}/problem_details.go (99%) rename internal/pkg/http/{http_errors/problemDetails => httperrors/problemdetails}/problem_details_test.go (98%) delete mode 100644 internal/pkg/postgresgorm/helpers.go create mode 100644 internal/pkg/postgresgorm/scopes/scopes.go rename internal/pkg/postgresmessaging/messagepersistence/{message_persistence_repository.go => postgres_message_service.go} (66%) rename internal/pkg/postgresmessaging/messagepersistence/{message_persistence_repository_test.go => postgres_message_service_test.go} (82%) rename internal/pkg/utils/{error_utils => errorutils}/errors.go (98%) rename internal/pkg/utils/{error_utils => errorutils}/errors_test.go (100%) delete mode 100644 internal/services/catalog_read_service/.env delete mode 100644 internal/services/catalog_write_service/.env rename internal/services/{catalog_read_service => catalogreadservice}/.air.toml (100%) rename internal/services/{catalog_read_service => catalogreadservice}/.dockerignore (100%) create mode 100644 internal/services/catalogreadservice/.env rename internal/services/{catalog_read_service => catalogreadservice}/.gitignore (100%) rename internal/services/{catalog_read_service => catalogreadservice}/.golangci.yml (100%) rename internal/services/{catalog_read_service => catalogreadservice}/Dockerfile (100%) rename internal/services/{catalog_read_service => catalogreadservice}/Makefile (100%) rename internal/services/{catalog_read_service => catalogreadservice}/arch-go.yml (100%) rename internal/services/{catalog_read_service => catalogreadservice}/client.http (100%) rename internal/services/{catalog_read_service => catalogreadservice}/cmd/app/main.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/cmd/migration/.gitkeep (100%) rename internal/services/{catalog_read_service => catalogreadservice}/config/config.development.json (95%) rename internal/services/{catalog_read_service => catalogreadservice}/config/config.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/config/config.test.json (95%) rename internal/services/{catalog_read_service => catalogreadservice}/config/confix_fx.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/docs/docs.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/docs/swagger.json (100%) rename internal/services/{catalog_read_service => catalogreadservice}/docs/swagger.yaml (100%) rename internal/services/{catalog_read_service => catalogreadservice}/go.mod (95%) rename internal/services/{catalog_read_service => catalogreadservice}/go.sum (92%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/configurations/mappings/mapping_profile.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/configurations/mediator/mediator_configurations.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/configurations/products_module_configurator.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/configurations/rabbitmq/rabbitmq_configuration.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/consts/consts.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/contracts/data/product_cache_repository.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/contracts/data/product_repository.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/contracts/params/product_route_params.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/data/repositories/mongo_product_repository.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/data/repositories/redis_product_repository.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/dto/product_dto.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/creating_product/v1/create_product.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/creating_product/v1/create_product_handler.go (98%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/creating_product/v1/dtos/create_product_response_dto.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created_consumer.go (97%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/deleting_products/v1/commands/delete_product.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/deleting_products/v1/commands/delete_product_handler.go (97%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted_consumer.go (97%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/get_product_by_id/v1/dtos/get_product_by_id_request_dto.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/get_product_by_id/v1/dtos/get_product_by_id_response_dto.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/get_product_by_id/v1/endpoints/get_product_by_id_endpoint.go (97%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/get_product_by_id/v1/queries/get_product_by_id.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/get_product_by_id/v1/queries/get_product_by_id_handler.go (98%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/getting_products/v1/dtos/get_products_request_dto.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/getting_products/v1/dtos/get_products_response_dto.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go (98%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/getting_products/v1/queries/get_products.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/getting_products/v1/queries/get_products_handler.go (97%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/searching_products/v1/dtos/search_products_request_dto.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/searching_products/v1/dtos/search_products_response_dto.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/searching_products/v1/endpoints/search_products_endpoint.go (98%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/searching_products/v1/queries/search_products.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/searching_products/v1/queries/search_products_handler.go (97%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/updating_products/v1/commands/update_product.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/updating_products/v1/commands/update_product_handler.go (98%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated_consumer.go (98%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/models/product.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/products/products_fx.go (98%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/shared/app/app.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/shared/app/application.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/shared/app/application_builder.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/shared/app/test/test_app.go (99%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/shared/app/test/test_application.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/shared/app/test/test_application_builder.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/shared/configurations/catalogs/catalogs_configurator.go (98%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go (94%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/shared/configurations/catalogs/catalogs_fx.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go (98%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/shared/contracts/catalogs_metrics.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/internal/shared/testfixture/integration/integration_test_fixture.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/mocks/ProductCacheRepository.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/mocks/ProductRepository.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/mocks/UnsafeProductsServiceServer.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/readme.md (100%) rename internal/services/{catalog_read_service => catalogreadservice}/revive-config.toml (100%) rename internal/services/{catalog_read_service => catalogreadservice}/staticcheck.conf (100%) rename internal/services/{catalog_read_service => catalogreadservice}/taskfile.yml (100%) rename internal/services/{catalog_read_service => catalogreadservice}/taskfile_db.yml (100%) rename internal/services/{catalog_read_service => catalogreadservice}/taskfile_test.yml (100%) rename internal/services/{catalog_read_service => catalogreadservice}/test/end_to_end/products/features/getting_product_by_id/v1/get_product_by_id_test.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/test/end_to_end/products/features/getting_products/v1/get_products_endpoint_test.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/test/integration/products/data/mongo_product_repository_test.go (99%) rename internal/services/{catalog_read_service => catalogreadservice}/test/integration/products/features/creating_product/v1/commands/create_product_test.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/test/integration/products/features/creating_product/v1/events/product_created_test.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/test/integration/products/features/deleting_product/v1/commands/delete_product_test.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/test/integration/products/features/deleting_product/v1/events/product_deleted_test.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/test/integration/products/features/getting_product_by_id/v1/queries/get_product_by_id_test.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/test/integration/products/features/getting_products/v1/queries/get_products_handler_test.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/test/integration/products/features/updating_product/v1/commands/update_product_handler_test.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/test/integration/products/features/updating_product/v1/events/product_updated_test.go (100%) rename internal/services/{catalog_read_service => catalogreadservice}/test/load_tests/.openapi-generator-ignore (100%) rename internal/services/{catalog_read_service => catalogreadservice}/test/load_tests/.openapi-generator/FILES (100%) rename internal/services/{catalog_read_service => catalogreadservice}/test/load_tests/.openapi-generator/VERSION (100%) rename internal/services/{catalog_read_service => catalogreadservice}/test/load_tests/README.md (100%) rename internal/services/{catalog_read_service => catalogreadservice}/test/load_tests/script.js (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/.air.toml (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/.dockerignore (100%) create mode 100644 internal/services/catalogwriteservice/.env rename internal/services/{catalog_write_service => catalogwriteservice}/.gitignore (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/.golangci.yml (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/Dockerfile (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/Makefile (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/arch-go.yml (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/atlas.hcl (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/client.http (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/cmd/app/main.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/cmd/migration/main.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/config/app_options.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/config/config.development.json (95%) rename internal/services/{catalog_write_service => catalogwriteservice}/config/config.test.json (94%) rename internal/services/{catalog_write_service => catalogwriteservice}/config/config_fx.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/fixtures/products/products.yaml (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/migrations/atlas/20230919170700.sql (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/migrations/atlas/atlas.sum (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/migrations/atlas/goose/00001_enable_uuid_extension.sql (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/migrations/atlas/goose/00002_create_products_table.sql (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/migrations/atlas/goose/atlas.sum (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/migrations/atlas/readme.md (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/migrations/go-migrate/000001_enable_uuid_extension.down.sql (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/migrations/go-migrate/000001_enable_uuid_extension.up.sql (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/migrations/go-migrate/000002_create_products_table.down.sql (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/migrations/go-migrate/000002_create_products_table.up.sql (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/migrations/go-migrate/atlas.sum (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/migrations/go-migrate/readme.md (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/migrations/go-migrate/schema.sql (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/migrations/goose-migrate/00001_enable_uuid_extension.sql (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/migrations/goose-migrate/00002_create_products_table.sql (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/db/migrations/goose-migrate/readme.md (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/docs/docs.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/docs/swagger.json (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/docs/swagger.yaml (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/go.mod (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/go.sum (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/configurations/endpoints/endpoints.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/configurations/mappings/mapping_profile.go (97%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/configurations/mediator/mediator.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/configurations/products_module_configurator.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/configurations/rabbitmq/rabbitmq_configurations.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/contracts/product_repository.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/data/models/product_data_model.go (56%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/data/repositories/pg_product_repository.go (92%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/dtos/v1/fxparams/product_handler_params.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/dtos/v1/fxparams/product_route_params.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/dtos/v1/product_dto.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/creatingproduct/v1/create_product.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/creatingproduct/v1/create_product_endpoint.go (97%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/creatingproduct/v1/create_product_handler.go (95%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/creatingproduct/v1/dtos/create_product_request_dto.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/creatingproduct/v1/dtos/create_product_response_dto.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/creatingproduct/v1/events/domainevents/.gitkeep (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/creatingproduct/v1/events/integrationevents/product_created.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/deletingproduct/v1/delete_product.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/deletingproduct/v1/delete_product_endpoint.go (97%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/deletingproduct/v1/delete_product_handler.go (95%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/deletingproduct/v1/dtos/delete_product_request_dto.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/deletingproduct/v1/events/integrationevents/product_deleted.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/gettingproductbyid/v1/dtos/get_product_by_id_request_dto.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/gettingproductbyid/v1/dtos/get_product_by_id_response_dto.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/gettingproductbyid/v1/get_product_by_id.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/gettingproductbyid/v1/get_product_by_id_endpoint.go (97%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/gettingproductbyid/v1/get_product_by_id_handler.go (94%) rename internal/services/{catalog_write_service/internal/products/features/getting_products => catalogwriteservice/internal/products/features/gettingproducts}/v1/dtos/get_products_request_dto.go (100%) rename internal/services/{catalog_write_service/internal/products/features/getting_products => catalogwriteservice/internal/products/features/gettingproducts}/v1/dtos/get_products_response_dto.go (100%) rename internal/services/{catalog_write_service/internal/products/features/getting_products => catalogwriteservice/internal/products/features/gettingproducts}/v1/get_products.go (100%) rename internal/services/{catalog_write_service/internal/products/features/getting_products => catalogwriteservice/internal/products/features/gettingproducts}/v1/get_products_endpoint.go (94%) rename internal/services/{catalog_write_service/internal/products/features/getting_products => catalogwriteservice/internal/products/features/gettingproducts}/v1/get_products_handler.go (89%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/searchingproduct/v1/dtos/search_products_request_dto.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/searchingproduct/v1/dtos/search_products_response_dto.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/searchingproduct/v1/search_products.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/searchingproduct/v1/search_products_endpoint.go (98%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/searchingproduct/v1/search_products_handler.go (97%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/updatingproduct/v1/dtos/update_product_request_dto.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/updatingproduct/v1/events/integrationevents/product_updated.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/updatingproduct/v1/update_product.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/updatingproduct/v1/update_product_endpoint.go (97%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/features/updatingproduct/v1/update_product_handler.go (96%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/models/product.go (90%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/products/products_fx.go (98%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/app/app.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/app/application.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/app/application_builder.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/app/test/test_app.go (96%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/app/test/test_application.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/app/test/test_application_builder.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/configurations/catalogs/catalogs_configurator.go (86%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/configurations/catalogs/catalogs_configurator_migration.go (72%) create mode 100644 internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator_seed.go rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go (94%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/configurations/catalogs/catalogs_fx.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go (98%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/contracts/catalogs_metrics.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/data/data_fx.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/data/dbcontext/catalogs_dbcontext.go (85%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/data/dbcontext/catalogs_dbcontext_test.go (67%) create mode 100644 internal/services/catalogwriteservice/internal/shared/data/scopes/scopes.go rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/grpc/genproto/products.pb.go (95%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/grpc/genproto/products_grpc.pb.go (98%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/grpc/product_grpc_service_server.go (97%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/testfixtures/integration/integration_test_fixture.go (92%) rename internal/services/{catalog_write_service => catalogwriteservice}/internal/shared/testfixtures/unittest/unit_test_fixture.go (71%) rename internal/services/{catalog_write_service => catalogwriteservice}/mocks/CatalogContext.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/mocks/ProductRepository.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/mocks/ProductsServiceClient.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/mocks/ProductsServiceServer.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/mocks/UnsafeProductsServiceServer.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/readme.md (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/revive-config.toml (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/taskfile.yml (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/taskfile_db.yml (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/taskfile_test.yml (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/endtoend/products/features/creatingproduct/v1/create_product_test.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/endtoend/products/features/deletingproduct/v1/delete_product_test.go (97%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/endtoend/products/features/gettingproductbyid/v1/get_product_by_id_test.go (97%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/endtoend/products/features/gettingproducts/v1/get_products_test.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/endtoend/products/features/searchingproduct/v1/search_products_test.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/endtoend/products/features/updatingproduct/v1/update_product_test.go (98%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/endtoend/products/grpc/product_grpc_service_server_test.go (93%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/integration/products/data/repositories/pg_product_repository_integration_test.go (94%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/integration/products/data/uow/catalogs_unit_of_work_integration_test.go (97%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/integration/products/features/creatingproduct/v1/create_product_test.go (98%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/integration/products/features/deletingproduct/v1/delete_product_test.go (98%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/integration/products/features/gettingproductbyid/v1/get_product_by_id_test.go (98%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/integration/products/features/gettingproducts/v1/get_products_test.go (97%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/integration/products/features/updatingproduct/v1/update_product_test.go (96%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/load/.openapi-generator-ignore (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/load/.openapi-generator/FILES (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/load/.openapi-generator/VERSION (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/load/README.md (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/load/script.js (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go (98%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/unit/products/features/creatingproduct/v1/create_product_unit_test.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/unit/products/features/deletingproduct/v1/delete_product_handler_unit_test.go (96%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/unit/products/features/deletingproduct/v1/delete_product_unit_test.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/unit/products/features/gettingproductbyid/v1/get_product_by_Id_unit_test.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/unit/products/features/gettingproductbyid/v1/get_product_by_id_handler_unit_test.go (92%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/unit/products/features/gettingproducts/v1/get_products_handler_unit_test.go (94%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/unit/products/features/searchingproducts/v1/search_products_unit_test.go (98%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/unit/products/features/updatingproduct/v1/update_product_handler_unit_test.go (92%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/unit/products/features/updatingproduct/v1/update_product_unit_test.go (100%) rename internal/services/{catalog_write_service => catalogwriteservice}/test/unit/products/mappings_profile_test.go (94%) delete mode 100644 internal/services/order_service/.env rename internal/services/{order_service => orderservice}/.air.toml (100%) rename internal/services/{order_service => orderservice}/.dockerignore (100%) create mode 100644 internal/services/orderservice/.env rename internal/services/{order_service => orderservice}/.golangci.yml (100%) rename internal/services/{order_service => orderservice}/Dockerfile (100%) rename internal/services/{order_service => orderservice}/Makefile (100%) rename internal/services/{order_service => orderservice}/arch-go.yml (100%) rename internal/services/{order_service => orderservice}/client.http (100%) rename internal/services/{order_service => orderservice}/cmd/app/main.go (100%) rename internal/services/{order_service => orderservice}/cmd/migration/.gitkeep (100%) rename internal/services/{order_service => orderservice}/config/config.development.json (95%) rename internal/services/{order_service => orderservice}/config/config.go (100%) rename internal/services/{order_service => orderservice}/config/config.test.json (95%) rename internal/services/{order_service => orderservice}/config/config_fx.go (100%) rename internal/services/{order_service => orderservice}/docs/docs.go (100%) rename internal/services/{order_service => orderservice}/docs/swagger.json (100%) rename internal/services/{order_service => orderservice}/docs/swagger.yaml (100%) rename internal/services/{order_service => orderservice}/go.mod (95%) rename internal/services/{order_service => orderservice}/go.sum (98%) rename internal/services/{order_service => orderservice}/internal/orders/configurations/mappings/mappings_profile.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/configurations/mediatr/mediator_configurations.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/configurations/orders_module_configurator.go (99%) rename internal/services/{order_service => orderservice}/internal/orders/configurations/rabbitmq/rabbitmq_configurations.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/contracts/params/order_projection_params.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/contracts/params/order_route_params.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/contracts/repositories/order_repository.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/data/repositories/elastic_order_read_repository.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/data/repositories/mongo_order_read_repository.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/dtos/v1/order_dto.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/dtos/v1/order_read_dto.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/dtos/v1/shopItem_dto.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/dtos/v1/shopItem_read_dto.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/exceptions/domain_exceptions/invalid_delivery_address_error.go (94%) rename internal/services/{order_service => orderservice}/internal/orders/exceptions/domain_exceptions/invalid_email_error.go (94%) rename internal/services/{order_service => orderservice}/internal/orders/exceptions/domain_exceptions/order_domain_errors_test.go (95%) rename internal/services/{order_service => orderservice}/internal/orders/exceptions/domain_exceptions/order_items_required_errors.go (94%) rename internal/services/{order_service => orderservice}/internal/orders/exceptions/domain_exceptions/order_not_found_error.go (94%) rename internal/services/{order_service => orderservice}/internal/orders/features/creating_order/v1/commands/create_order.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/features/creating_order/v1/commands/create_order_handler.go (98%) rename internal/services/{order_service => orderservice}/internal/orders/features/creating_order/v1/dtos/create_order_request_dto.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/features/creating_order/v1/dtos/create_order_response_dto.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/features/creating_order/v1/endpoints/create_order_endpoint.go (98%) rename internal/services/{order_service => orderservice}/internal/orders/features/creating_order/v1/events/domain_events/order_created.go (98%) rename internal/services/{order_service => orderservice}/internal/orders/features/creating_order/v1/events/integration_events/order_created.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/features/getting_order_by_id/v1/dtos/get_order_by_id_request_dto.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/features/getting_order_by_id/v1/dtos/get_order_by_id_response_dto.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/features/getting_order_by_id/v1/endpoints/get_order_by_id_endpoint.go (98%) rename internal/services/{order_service => orderservice}/internal/orders/features/getting_order_by_id/v1/queries/get_order_by_id.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/features/getting_order_by_id/v1/queries/get_order_by_id_handler.go (98%) rename internal/services/{order_service => orderservice}/internal/orders/features/getting_orders/v1/dtos/get_orders_request_dto.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/features/getting_orders/v1/dtos/get_orders_response_dto.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/features/getting_orders/v1/endpoints/get_orders_endpoint.go (98%) rename internal/services/{order_service => orderservice}/internal/orders/features/getting_orders/v1/queries/get_orders.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/features/getting_orders/v1/queries/get_orders_handler.go (98%) rename internal/services/{order_service => orderservice}/internal/orders/features/submitting_order/v1/commands/submit_order.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/features/submitting_order/v1/events/domain_events/order_submitted.go (91%) rename internal/services/{order_service => orderservice}/internal/orders/features/updating_shopping_card/v1/commands/update_shopping_card.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/features/updating_shopping_card/v1/events/shopping_card_updated.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/models/orders/aggregate/order.go (99%) rename internal/services/{order_service => orderservice}/internal/orders/models/orders/read_models/order_read.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/models/orders/read_models/shop_item_read.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/models/orders/value_objects/shop_item.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/orders_fx.go (98%) rename internal/services/{order_service => orderservice}/internal/orders/projections/elastic_order_projection.go (100%) rename internal/services/{order_service => orderservice}/internal/orders/projections/mongo_order_projection.go (99%) rename internal/services/{order_service => orderservice}/internal/shared/app/app.go (100%) rename internal/services/{order_service => orderservice}/internal/shared/app/application.go (100%) rename internal/services/{order_service => orderservice}/internal/shared/app/application_builder.go (100%) rename internal/services/{order_service => orderservice}/internal/shared/app/test/test_app.go (99%) rename internal/services/{order_service => orderservice}/internal/shared/app/test/test_application.go (100%) rename internal/services/{order_service => orderservice}/internal/shared/app/test/test_application_builder.go (100%) rename internal/services/{order_service => orderservice}/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go (100%) rename internal/services/{order_service => orderservice}/internal/shared/configurations/orders/infrastructure/infrastructure_fx.go (98%) rename internal/services/{order_service => orderservice}/internal/shared/configurations/orders/orders_configurator.go (98%) rename internal/services/{order_service => orderservice}/internal/shared/configurations/orders/orders_configurator_swagger.go (93%) rename internal/services/{order_service => orderservice}/internal/shared/configurations/orders/orders_fx.go (100%) rename internal/services/{order_service => orderservice}/internal/shared/contracts/orders_metrics.go (100%) rename internal/services/{order_service => orderservice}/internal/shared/grpc/genproto/orders.pb.go (99%) rename internal/services/{order_service => orderservice}/internal/shared/grpc/genproto/orders_grpc.pb.go (99%) rename internal/services/{order_service => orderservice}/internal/shared/grpc/order_grpc_service_server.go (99%) rename internal/services/{order_service => orderservice}/internal/shared/test_fixtures/integration/integration_test_fixture.go (100%) rename internal/services/{order_service => orderservice}/mocks/InvalidDeliveryAddressError.go (100%) rename internal/services/{order_service => orderservice}/mocks/InvalidEmailAddressError.go (100%) rename internal/services/{order_service => orderservice}/mocks/OrderElasticRepository.go (100%) rename internal/services/{order_service => orderservice}/mocks/OrderMongoRepository.go (100%) rename internal/services/{order_service => orderservice}/mocks/OrderNotFoundError.go (100%) rename internal/services/{order_service => orderservice}/mocks/OrderShopItemsRequiredError.go (100%) rename internal/services/{order_service => orderservice}/mocks/OrdersServiceClient.go (100%) rename internal/services/{order_service => orderservice}/mocks/OrdersServiceServer.go (100%) rename internal/services/{order_service => orderservice}/mocks/UnsafeOrdersServiceServer.go (100%) rename internal/services/{order_service => orderservice}/mocks/orderReadRepository.go (100%) rename internal/services/{order_service => orderservice}/readme.md (100%) rename internal/services/{order_service => orderservice}/revive-config.toml (100%) rename internal/services/{order_service => orderservice}/taskfile.yml (100%) rename internal/services/{order_service => orderservice}/taskfile_db.yml (100%) rename internal/services/{order_service => orderservice}/taskfile_test.yml (100%) rename internal/services/{order_service => orderservice}/test/end_to_end/orders/features/creating_order/v1/create_order_test.go (100%) rename internal/services/{order_service => orderservice}/test/end_to_end/orders/features/getting_order_by_id/v1/get_order_by_id_test.go (100%) rename internal/services/{order_service => orderservice}/test/end_to_end/orders/grpc/order_grpc_service_server_test.go (100%) rename internal/services/{order_service => orderservice}/test/integration/orders/features/creating_order/v1/create_order_test.go (100%) rename internal/services/{order_service => orderservice}/test/integration/orders/features/getting_order_by_id/v1/get_order_by_id_test.go (100%) diff --git a/Makefile b/Makefile index eb60a135..fb6aa917 100644 --- a/Makefile +++ b/Makefile @@ -4,36 +4,36 @@ install-tools: .PHONY: run-catalogs-write-service run-catalogs-write-service: - @./scripts/run.sh catalog_write_service + @./scripts/run.sh catalogwriteservice .PHONY: run-catalog-read-service run-catalog-read-service: - @./scripts/run.sh catalog_read_service + @./scripts/run.sh catalogreadservice .PHONY: run-order-service run-order-service: - @./scripts/run.sh order_service + @./scripts/run.sh orderservice .PHONY: build build: @./scripts/build.sh pkg - @./scripts/build.sh catalog_write_service - @./scripts/build.sh catalog_read_service - @./scripts/build.sh order_service + @./scripts/build.sh catalogwriteservice + @./scripts/build.sh catalogreadservice + @./scripts/build.sh orderservice .PHONY: update-dependencies update-dependencies: @./scripts/update-dependencies.sh pkg - @./scripts/update-dependencies.sh catalog_write_service - @./scripts/update-dependencies.sh catalog_read_service - @./scripts/update-dependencies.sh order_service + @./scripts/update-dependencies.sh catalogwriteservice + @./scripts/update-dependencies.sh catalogreadservice + @./scripts/update-dependencies.sh orderservice .PHONY: install-dependencies install-dependencies: @./scripts/install-dependencies.sh pkg - @./scripts/install-dependencies.sh catalog_write_service - @./scripts/install-dependencies.sh catalog_read_service - @./scripts/install-dependencies.sh order_service + @./scripts/install-dependencies.sh catalogwriteservice + @./scripts/install-dependencies.sh catalogreadservice + @./scripts/install-dependencies.sh orderservice .PHONY: docker-compose-infra-up docker-compose-infra-up: @@ -44,33 +44,33 @@ docker-compose-infra-down: .PHONY: openapi openapi: - @./scripts/openapi.sh catalog_write_service - @./scripts/openapi.sh catalog_read_service - @./scripts/openapi.sh order_service + @./scripts/openapi.sh catalogwriteservice + @./scripts/openapi.sh catalogreadservice + @./scripts/openapi.sh orderservice # https://stackoverflow.com/questions/13616033/install-protocol-buffers-on-windows .PHONY: proto proto: - @./scripts/proto.sh catalog_write_service - @./scripts/proto.sh order_service + @./scripts/proto.sh catalogwriteservice + @./scripts/proto.sh orderservice .PHONY: unit-test unit-test: - @./scripts/test.sh catalog_read_service unit - @./scripts/test.sh catalog_write_service unit - @./scripts/test.sh order_service unit + @./scripts/test.sh catalogreadservice unit + @./scripts/test.sh catalogwriteservice unit + @./scripts/test.sh orderservice unit .PHONY: integration-test integration-test: - @./scripts/test.sh catalog_read_service integration - @./scripts/test.sh catalog_write_service integration - @./scripts/test.sh order_service integration + @./scripts/test.sh catalogreadservice integration + @./scripts/test.sh catalogwriteservice integration + @./scripts/test.sh orderservice integration .PHONY: e2e-test e2e-test: - @./scripts/test.sh catalog_read_service e2e - @./scripts/test.sh catalog_write_service e2e - @./scripts/test.sh order_service e2e + @./scripts/test.sh catalogreadservice e2e + @./scripts/test.sh catalogwriteservice e2e + @./scripts/test.sh orderservice e2e #.PHONY: load-test #load-test: @@ -80,16 +80,16 @@ e2e-test: .PHONY: format format: - @./scripts/format.sh catalog_write_service - @./scripts/format.sh catalog_read_service - @./scripts/format.sh order_service + @./scripts/format.sh catalogwriteservice + @./scripts/format.sh catalogreadservice + @./scripts/format.sh orderservice @./scripts/format.sh pkg .PHONY: lint lint: - @./scripts/lint.sh catalog_write_service - @./scripts/lint.sh catalog_read_service - @./scripts/lint.sh order_service + @./scripts/lint.sh catalogwriteservice + @./scripts/lint.sh catalogreadservice + @./scripts/lint.sh orderservice @./scripts/lint.sh pkg # https://github.com/golang-migrate/migrate/blob/856ea12df9d230b0145e23d951b7dbd6b86621cb/database/postgres/TUTORIAL.md @@ -98,30 +98,29 @@ lint: # https://github.com/golang-migrate/migrate/tree/856ea12df9d230b0145e23d951b7dbd6b86621cb/cmd/migrate#usage .PHONY: go-migrate go-migrate: - @./scripts/go-migrate.sh -p ./internal/services/catalog_write_service/db/migrations/go-migrate -c create -n create_product_table - @./scripts/go-migrate.sh -p ./internal/services/catalog_write_service/db/migrations/go-migrate -c up -o postgres://postgres:postgres@localhost:5432/catalogs_service?sslmode=disable - @./scripts/go-migrate.sh -p ./internal/services/catalog_write_service/db/migrations/go-migrate -c down -o postgres://postgres:postgres@localhost:5432/catalogs_service?sslmode=disable + @./scripts/go-migrate.sh -p ./internal/services/catalogwriteservice/db/migrations/go-migrate -c create -n create_product_table + @./scripts/go-migrate.sh -p ./internal/services/catalogwriteservice/db/migrations/go-migrate -c up -o postgres://postgres:postgres@localhost:5432/catalogs_service?sslmode=disable + @./scripts/go-migrate.sh -p ./internal/services/catalogwriteservice/db/migrations/go-migrate -c down -o postgres://postgres:postgres@localhost:5432/catalogs_service?sslmode=disable # https://github.com/pressly/goose#usage .PHONY: goose-migrate goose-migrate: - @./scripts/goose-migrate.sh -p ./internal/services/catalog_write_service/db/migrations/goose-migrate -c create -n create_product_table - @./scripts/goose-migrate.sh -p ./internal/services/catalog_write_service/db/migrations/goose-migrate -c up -o "user=postgres password=postgres dbname=catalogs_service sslmode=disable" - @./scripts/goose-migrate.sh -p ./internal/services/catalog_write_service/db/migrations/goose-migrate -c down -o "user=postgres password=postgres dbname=catalogs_service sslmode=disable" + @./scripts/goose-migrate.sh -p ./internal/services/catalogwriteservice/db/migrations/goose-migrate -c create -n create_product_table + @./scripts/goose-migrate.sh -p ./internal/services/catalogwriteservice/db/migrations/goose-migrate -c up -o "user=postgres password=postgres dbname=catalogs_service sslmode=disable" + @./scripts/goose-migrate.sh -p ./internal/services/catalogwriteservice/db/migrations/goose-migrate -c down -o "user=postgres password=postgres dbname=catalogs_service sslmode=disable" # https://atlasgo.io/guides/orms/gorm .PHONY: atlas atlas: - @./scripts/atlas-migrate.sh -c gorm-sync -p "./internal/services/catalog_write_service" - @./scripts/atlas-migrate.sh -c apply -p "./internal/services/catalog_write_service" -o "postgres://postgres:postgres@localhost:5432/catalogs_service?sslmode=disable" + @./scripts/atlas-migrate.sh -c gorm-sync -p "./internal/services/catalogwriteservice" + @./scripts/atlas-migrate.sh -c apply -p "./internal/services/catalogwriteservice" -o "postgres://postgres:postgres@localhost:5432/catalogs_service?sslmode=disable" .PHONY: cycle-check cycle-check: - cd internal/services/catalog_write_service && goimportcycle -dot imports.dot dot -Tpng -o cycle/catalog_write_service.png imports.dot - cd internal/services/catalog_write_service && goimportcycle -dot imports.dot dot -Tpng -o cycle/catalog_write_service.png imports.dot - cd internal/services/catalog_read_service && goimportcycle -dot imports.dot dot -Tpng -o cycle/catalog_read_service.png imports.dot cd internal/pkg && goimportcycle -dot imports.dot dot -Tpng -o cycle/pkg.png imports.dot - + cd internal/services/catalogwriteservice && goimportcycle -dot imports.dot dot -Tpng -o cycle/catalogwriteservice.png imports.dot + cd internal/services/catalogwriteservice && goimportcycle -dot imports.dot dot -Tpng -o cycle/catalogwriteservice.png imports.dot + cd internal/services/orderservice && goimportcycle -dot imports.dot dot -Tpng -o cycle/orderservice.png imports.dot #.PHONY: c4 #c4: @@ -138,6 +137,6 @@ pkg-mocks: .PHONY: services-mocks services-mocks: - cd internal/services/catalog_write_service && mockery --output mocks --all - cd internal/services/catalog_read_service && mockery --output mocks --all - cd internal/services/order_service && mockery --output mocks --all + cd internal/services/catalogwriteservice && mockery --output mocks --all + cd internal/services/catalogreadservice && mockery --output mocks --all + cd internal/services/orderservice && mockery --output mocks --all diff --git a/api/openapi/catalog_read_service/docs.go b/api/openapi/catalogreadservice/docs.go similarity index 99% rename from api/openapi/catalog_read_service/docs.go rename to api/openapi/catalogreadservice/docs.go index 1c44e7b8..c6384bf4 100644 --- a/api/openapi/catalog_read_service/docs.go +++ b/api/openapi/catalogreadservice/docs.go @@ -1,6 +1,6 @@ // Code generated by swaggo/swag. DO NOT EDIT. -package catalog_read_service +package catalogreadservice import "github.com/swaggo/swag" diff --git a/api/openapi/catalog_read_service/swagger.json b/api/openapi/catalogreadservice/swagger.json similarity index 100% rename from api/openapi/catalog_read_service/swagger.json rename to api/openapi/catalogreadservice/swagger.json diff --git a/api/openapi/catalog_read_service/swagger.yaml b/api/openapi/catalogreadservice/swagger.yaml similarity index 100% rename from api/openapi/catalog_read_service/swagger.yaml rename to api/openapi/catalogreadservice/swagger.yaml diff --git a/api/openapi/catalog_write_service/docs.go b/api/openapi/catalogwriteservice/docs.go similarity index 99% rename from api/openapi/catalog_write_service/docs.go rename to api/openapi/catalogwriteservice/docs.go index 5f8aa576..ca894145 100644 --- a/api/openapi/catalog_write_service/docs.go +++ b/api/openapi/catalogwriteservice/docs.go @@ -1,6 +1,6 @@ // Code generated by swaggo/swag. DO NOT EDIT. -package catalog_write_service +package catalogwriteservice import "github.com/swaggo/swag" diff --git a/api/openapi/catalog_write_service/swagger.json b/api/openapi/catalogwriteservice/swagger.json similarity index 100% rename from api/openapi/catalog_write_service/swagger.json rename to api/openapi/catalogwriteservice/swagger.json diff --git a/api/openapi/catalog_write_service/swagger.yaml b/api/openapi/catalogwriteservice/swagger.yaml similarity index 100% rename from api/openapi/catalog_write_service/swagger.yaml rename to api/openapi/catalogwriteservice/swagger.yaml diff --git a/api/openapi/order_service/docs.go b/api/openapi/orderservice/docs.go similarity index 99% rename from api/openapi/order_service/docs.go rename to api/openapi/orderservice/docs.go index 934905f3..119e33d6 100644 --- a/api/openapi/order_service/docs.go +++ b/api/openapi/orderservice/docs.go @@ -1,6 +1,6 @@ // Code generated by swaggo/swag. DO NOT EDIT. -package order_service +package orderservice import "github.com/swaggo/swag" diff --git a/api/openapi/order_service/swagger.json b/api/openapi/orderservice/swagger.json similarity index 100% rename from api/openapi/order_service/swagger.json rename to api/openapi/orderservice/swagger.json diff --git a/api/openapi/order_service/swagger.yaml b/api/openapi/orderservice/swagger.yaml similarity index 100% rename from api/openapi/order_service/swagger.yaml rename to api/openapi/orderservice/swagger.yaml diff --git a/api/protobuf/catalog_write_service/products.proto b/api/protobuf/catalogwriteservice/products.proto similarity index 100% rename from api/protobuf/catalog_write_service/products.proto rename to api/protobuf/catalogwriteservice/products.proto diff --git a/api/protobuf/order_service/orders.proto b/api/protobuf/orderservice/orders.proto similarity index 100% rename from api/protobuf/order_service/orders.proto rename to api/protobuf/orderservice/orders.proto diff --git a/deployments/docker-compose/docker-compose.infrastructure.yaml b/deployments/docker-compose/docker-compose.infrastructure.yaml index 2c7144e3..4b24e5c7 100644 --- a/deployments/docker-compose/docker-compose.infrastructure.yaml +++ b/deployments/docker-compose/docker-compose.infrastructure.yaml @@ -45,20 +45,20 @@ services: networks: - ecommerce - # node_exporter will use for gathering metrics on the system level with its own /metrics endpoint like cpu, ram, ... - # https://prometheus.io/docs/guides/node-exporter/ - node_exporter: - container_name: node_exporter - pull_policy: if_not_present - restart: unless-stopped - image: prom/node-exporter - ports: - - "9100:9100" - networks: - - ecommerce +# # node_exporter will use for gathering metrics on the system level with its own /metrics endpoint (http://localhost:9100/metrics) like cpu, ram, ... +# # https://prometheus.io/docs/guides/node-exporter/ +# node_exporter: +# container_name: node_exporter +# pull_policy: if_not_present +# restart: unless-stopped +# image: prom/node-exporter +# ports: +# - "9100:9100" +# networks: +# - ecommerce grafana: - image: grafana/grafana + image: grafana/grafana:latest pull_policy: if_not_present container_name: grafana restart: unless-stopped @@ -103,13 +103,13 @@ services: networks: - ecommerce -# k6-tracing: -# image: ghcr.io/grafana/xk6-client-tracing:latest -# environment: -# - ENDPOINT=tempo:4317 -# restart: always -# depends_on: -# - tempo +# # k6-tracing: +# # image: ghcr.io/grafana/xk6-client-tracing:latest +# # environment: +# # - ENDPOINT=tempo:4317 +# # restart: always +# # depends_on: +# # - tempo postgres: image: postgres:latest @@ -138,7 +138,7 @@ services: - ecommerce mongo: - image: mongo + image: mongo:latest pull_policy: if_not_present container_name: mongo restart: unless-stopped @@ -191,15 +191,15 @@ services: networks: - ecommerce - zipkin: - image: openzipkin/zipkin:latest - pull_policy: if_not_present - restart: unless-stopped - container_name: zipkin - ports: - - "9411:9411" - networks: - - ecommerce +# zipkin: +# image: openzipkin/zipkin:latest +# pull_policy: if_not_present +# restart: unless-stopped +# container_name: zipkin +# ports: +# - "9411:9411" +# networks: +# - ecommerce # https://developers.eventstore.com/server/v21.10/installation.html#insecure-single-node # https://hub.docker.com/r/eventstore/eventstore/tags @@ -233,135 +233,135 @@ services: networks: - ecommerce - # containers monitoring - cadvisor: - image: gcr.io/cadvisor/cadvisor:latest - restart: unless-stopped - ports: - - "9091:8080" - # network_mode: host - volumes: - - /:/rootfs:ro - - /var/run:/var/run:ro - - /sys:/sys:ro - - /var/lib/docker/:/var/lib/docker:ro - - /dev/disk/:/dev/disk:ro - devices: - - /dev/kmsg - networks: - - ecommerce +# # containers monitoring - Analyzes resource usage and performance characteristics of running containers. +# cadvisor: +# image: gcr.io/cadvisor/cadvisor:latest +# restart: unless-stopped +# ports: +# - "9091:8080" +# # network_mode: host +# volumes: +# - /:/rootfs:ro +# - /var/run:/var/run:ro +# - /sys:/sys:ro +# - /var/lib/docker/:/var/lib/docker:ro +# - /dev/disk/:/dev/disk:ro +# devices: +# - /dev/kmsg +# networks: +# - ecommerce -# # https://stackoverflow.com/questions/67791781/how-to-configure-apm-server-to-docker-compose-file -# # https://www.elastic.co/guide/en/apm/guide/current/open-telemetry.html -# apm-server: -# image: docker.elastic.co/apm/apm-server:latest -# cap_add: ["CHOWN", "DAC_OVERRIDE", "SETGID", "SETUID"] -# cap_drop: ["ALL"] -# ports: -# - 8200:8200 -# command: > -# apm-server -e -# -E apm-server.rum.enabled=true -# -E setup.kibana.host=kibana:5601 -# -E setup.template.settings.index.number_of_replicas=0 -# -E apm-server.kibana.enabled=true -# -E apm-server.kibana.host=kibana:5601 -# -E output.elasticsearch.hosts=["elasticsearch:9200"] +# # # https://stackoverflow.com/questions/67791781/how-to-configure-apm-server-to-docker-compose-file +# # # https://www.elastic.co/guide/en/apm/guide/current/open-telemetry.html +# # apm-server: +# # image: docker.elastic.co/apm/apm-server:latest +# # cap_add: ["CHOWN", "DAC_OVERRIDE", "SETGID", "SETUID"] +# # cap_drop: ["ALL"] +# # ports: +# # - 8200:8200 +# # command: > +# # apm-server -e +# # -E apm-server.rum.enabled=true +# # -E setup.kibana.host=kibana:5601 +# # -E setup.template.settings.index.number_of_replicas=0 +# # -E apm-server.kibana.enabled=true +# # -E apm-server.kibana.host=kibana:5601 +# # -E output.elasticsearch.hosts=["elasticsearch:9200"] - # elasticsearch: - # container_name: elastic_search - # restart: unless-stopped - # image: elasticsearch:8.5.2 - # environment: - # - discovery.type=single-node - # - bootstrap.memory_lock=true - # - xpack.monitoring.enabled=true - # - xpack.watcher.enabled=false - # - "ES_JAVA_OPTS=-Xms512m -Xmx512m" - # ulimits: - # memlock: - # soft: -1 - # hard: -1 - # volumes: - # - elastic-data:/usr/share/elasticsearch/data - # ports: - # - ${ELASTIC_HOST_PORT:-9200}:${ELASTIC_PORT:-9200} - # - 9300:9300 - # networks: - # - ecommerce +# # elasticsearch: +# # container_name: elastic_search +# # restart: unless-stopped +# # image: elasticsearch:8.5.2 +# # environment: +# # - discovery.type=single-node +# # - bootstrap.memory_lock=true +# # - xpack.monitoring.enabled=true +# # - xpack.watcher.enabled=false +# # - "ES_JAVA_OPTS=-Xms512m -Xmx512m" +# # ulimits: +# # memlock: +# # soft: -1 +# # hard: -1 +# # volumes: +# # - elastic-data:/usr/share/elasticsearch/data +# # ports: +# # - ${ELASTIC_HOST_PORT:-9200}:${ELASTIC_PORT:-9200} +# # - 9300:9300 +# # networks: +# # - ecommerce - # kibana: - # image: kibana:8.5.2 - # container_name: kibana - # restart: unless-stopped - # environment: - # - ELASTICSEARCH_HOSTS=http://elastic_search:${ELASTIC_PORT:-9200} - # ports: - # - ${KIBANA_HOST_PORT:-5601}:${KIBANA_PORT:-5601} - # networks: - # - ecommerce - # depends_on: - # - elasticsearch +# # kibana: +# # image: kibana:8.5.2 +# # container_name: kibana +# # restart: unless-stopped +# # environment: +# # - ELASTICSEARCH_HOSTS=http://elastic_search:${ELASTIC_PORT:-9200} +# # ports: +# # - ${KIBANA_HOST_PORT:-5601}:${KIBANA_PORT:-5601} +# # networks: +# # - ecommerce +# # depends_on: +# # - elasticsearch - # zookeeper: - # image: confluentinc/cp-zookeeper:7.0.1 - # hostname: zookeeper - # container_name: zookeeper - # restart: unless-stopped - # ports: - # - "2181:2181" - # environment: - # ZOOKEEPER_CLIENT_PORT: 2181 - # ZOOKEEPER_TICK_TIME: 2000 - # networks: - # - ecommerce +# # zookeeper: +# # image: confluentinc/cp-zookeeper:7.0.1 +# # hostname: zookeeper +# # container_name: zookeeper +# # restart: unless-stopped +# # ports: +# # - "2181:2181" +# # environment: +# # ZOOKEEPER_CLIENT_PORT: 2181 +# # ZOOKEEPER_TICK_TIME: 2000 +# # networks: +# # - ecommerce - # kafka: - # image: confluentinc/cp-kafka:7.0.1 - # hostname: kafka - # container_name: kafka - # restart: unless-stopped - # depends_on: - # - zookeeper - # ports: - # - "9092:9092" - # environment: - # KAFKA_BROKER_ID: 1 - # KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181' - # KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT - # KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 - # KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 - # ADVERTISED_HOST_NAME: kafka - # KAFKA_ADVERTISED_HOSTNAME: 127.0.0.1 - # networks: - # - ecommerce +# # kafka: +# # image: confluentinc/cp-kafka:7.0.1 +# # hostname: kafka +# # container_name: kafka +# # restart: unless-stopped +# # depends_on: +# # - zookeeper +# # ports: +# # - "9092:9092" +# # environment: +# # KAFKA_BROKER_ID: 1 +# # KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181' +# # KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT +# # KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 +# # KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 +# # ADVERTISED_HOST_NAME: kafka +# # KAFKA_ADVERTISED_HOSTNAME: 127.0.0.1 +# # networks: +# # - ecommerce - # kafka-ui: - # image: provectuslabs/kafka-ui - # container_name: kafka-ui - # ports: - # - "8080:8080" - # restart: always - # environment: - # - KAFKA_CLUSTERS_0_NAME=local - # - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:9092 - # - KAFKA_CLUSTERS_0_ZOOKEEPER=zookeeper:2181 +# # kafka-ui: +# # image: provectuslabs/kafka-ui +# # container_name: kafka-ui +# # ports: +# # - "8080:8080" +# # restart: always +# # environment: +# # - KAFKA_CLUSTERS_0_NAME=local +# # - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:9092 +# # - KAFKA_CLUSTERS_0_ZOOKEEPER=zookeeper:2181 - # kafdrop: - # image: obsidiandynamics/kafdrop - # container_name: kafdrop - # ports: - # - '9000:9000' - # environment: - # - 'KAFKA_BROKERCONNECT=' - # - 'JVM_OPTS=-Xms32M -Xmx64M' - # - SERVER_SERVLET_CONTEXTPATH=/ +# # kafdrop: +# # image: obsidiandynamics/kafdrop +# # container_name: kafdrop +# # ports: +# # - '9000:9000' +# # environment: +# # - 'KAFKA_BROKERCONNECT=' +# # - 'JVM_OPTS=-Xms32M -Xmx64M' +# # - SERVER_SERVLET_CONTEXTPATH=/ volumes: eventstore-volume-data: eventstore-volume-logs: - elastic-data: +# elastic-data: networks: ecommerce: diff --git a/deployments/docker-compose/monitoring/prometheus.yml b/deployments/docker-compose/monitoring/prometheus.yml index 582ba0f4..39e05870 100644 --- a/deployments/docker-compose/monitoring/prometheus.yml +++ b/deployments/docker-compose/monitoring/prometheus.yml @@ -47,7 +47,7 @@ scrape_configs: # http://localhost:8000/metrics # localhost doesn't work here because inner prometheus container localhost will infer to localhost inner the container which is different with system localhost. for access to actual system localhost we should use `host.docker.internal` # instead of `localhost` to access node_exporter container inner prometheus container we can use our container network name to access this container because they are in same docker-compose and same default network - - job_name: order_service + - job_name: orderservice scrape_interval: 1s static_configs: - targets: [ "host.docker.internal:8000" ] diff --git a/deployments/docker-compose/traefik.yaml b/deployments/docker-compose/traefik.yaml index ba35cfd1..9233b9bc 100644 --- a/deployments/docker-compose/traefik.yaml +++ b/deployments/docker-compose/traefik.yaml @@ -141,9 +141,9 @@ - + - + diff --git a/internal/pkg/core/core_fx.go b/internal/pkg/core/core_fx.go index e853947c..fd3df78a 100644 --- a/internal/pkg/core/core_fx.go +++ b/internal/pkg/core/core_fx.go @@ -1,7 +1,6 @@ package core import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/json" "go.uber.org/fx" @@ -12,8 +11,9 @@ import ( var Module = fx.Module( "corefx", fx.Provide( - json.NewDefaultSerializer, - serializer.NewDefaultEventSerializer, - serializer.NewDefaultMetadataSerializer, + json.NewDefaultJsonSerializer, + json.NewDefaultEventJsonSerializer, + json.NewDefaultMessageJsonSerializer, + json.NewDefaultMetadataJsonSerializer, ), ) diff --git a/internal/pkg/core/customtypes/custom_time.go b/internal/pkg/core/customtypes/custom_time.go index 57791650..1e03d73d 100644 --- a/internal/pkg/core/customtypes/custom_time.go +++ b/internal/pkg/core/customtypes/custom_time.go @@ -8,7 +8,7 @@ import ( "strings" "time" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/araddon/dateparse" ) diff --git a/internal/pkg/core/events/event.go b/internal/pkg/core/events/event.go index e97e19d9..a8f12405 100644 --- a/internal/pkg/core/events/event.go +++ b/internal/pkg/core/events/event.go @@ -3,13 +3,17 @@ package events import ( "time" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" + uuid "github.com/satori/go.uuid" ) type IEvent interface { GetEventId() uuid.UUID - GetEventType() string GetOccurredOn() time.Time + // GetEventTypeName get short type name of the event - we use event short type name instead of full type name because this event in other receiver packages could have different package name + GetEventTypeName() string + GetEventFullTypeName() string } type Event struct { @@ -37,3 +41,11 @@ func (e *Event) GetEventType() string { func (e *Event) GetOccurredOn() time.Time { return e.OccurredOn } + +func (e *Event) GetEventTypeName() string { + return typeMapper.GetTypeName(e) +} + +func (e *Event) GetEventFullTypeName() string { + return typeMapper.GetFullTypeName(e) +} diff --git a/internal/pkg/core/messaging/mocks/IMessage.go b/internal/pkg/core/messaging/mocks/IMessage.go index 95db2f29..c7e7b3b6 100644 --- a/internal/pkg/core/messaging/mocks/IMessage.go +++ b/internal/pkg/core/messaging/mocks/IMessage.go @@ -104,7 +104,7 @@ func (_c *IMessage_GetCreated_Call) RunAndReturn(run func() time.Time) *IMessage } // GetEventTypeName provides a mock function with given fields: -func (_m *IMessage) GetEventTypeName() string { +func (_m *IMessage) GetMessageTypeName() string { ret := _m.Called() var r0 string @@ -117,14 +117,14 @@ func (_m *IMessage) GetEventTypeName() string { return r0 } -// IMessage_GetEventTypeName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEventTypeName' +// IMessage_GetEventTypeName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetMessageTypeName' type IMessage_GetEventTypeName_Call struct { *mock.Call } // GetEventTypeName is a helper method to define mock.On call func (_e *IMessage_Expecter) GetEventTypeName() *IMessage_GetEventTypeName_Call { - return &IMessage_GetEventTypeName_Call{Call: _e.mock.On("GetEventTypeName")} + return &IMessage_GetEventTypeName_Call{Call: _e.mock.On("GetMessageTypeName")} } func (_c *IMessage_GetEventTypeName_Call) Run(run func()) *IMessage_GetEventTypeName_Call { @@ -223,7 +223,8 @@ func (_c *IMessage_SetEventTypeName_Call) RunAndReturn(run func(string)) *IMessa func NewIMessage(t interface { mock.TestingT Cleanup(func()) -}) *IMessage { +}, +) *IMessage { mock := &IMessage{} mock.Mock.Test(t) diff --git a/internal/pkg/core/messaging/otel/tracing/producer/producer.go b/internal/pkg/core/messaging/otel/tracing/producer/producer.go index ec504151..81315286 100644 --- a/internal/pkg/core/messaging/otel/tracing/producer/producer.go +++ b/internal/pkg/core/messaging/otel/tracing/producer/producer.go @@ -111,7 +111,7 @@ func getTraceOptions( semconv.MessageIDKey.String(message.GeMessageId()), semconv.MessagingMessageConversationID(correlationId), attribute.Key(tracing.MessageType). - String(message.GetEventTypeName()), + String(message.GetMessageTypeName()), attribute.Key(tracing.MessageName). String(messageHeader.GetMessageName(*meta)), attribute.Key(tracing.Payload).String(payload), diff --git a/internal/pkg/core/messaging/persistmessage/message_persistence_service.go b/internal/pkg/core/messaging/persistmessage/message_persistence_service.go deleted file mode 100644 index 7ae6258a..00000000 --- a/internal/pkg/core/messaging/persistmessage/message_persistence_service.go +++ /dev/null @@ -1,24 +0,0 @@ -package persistmessage - -import ( - "context" - - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" -) - -type IMessagePersistenceService interface { - GetByFilter( - predicate func(StoreMessage) bool, - ctx context.Context, - ) ([]StoreMessage, error) - AddPublishMessage( - messageEnvelope types.MessageEnvelopeTMessage, - ctx context.Context, - ) error - AddReceivedMessage( - messageEnvelope types.MessageEnvelope, - ctx context.Context, - ) error - Process(messageID string, ctx context.Context) error - ProcessAll(ctx context.Context) error -} diff --git a/internal/pkg/core/messaging/persistmessage/message_persistence_repository.go b/internal/pkg/core/messaging/persistmessage/message_service.go similarity index 61% rename from internal/pkg/core/messaging/persistmessage/message_persistence_repository.go rename to internal/pkg/core/messaging/persistmessage/message_service.go index 59d5c3f3..163deb03 100644 --- a/internal/pkg/core/messaging/persistmessage/message_persistence_repository.go +++ b/internal/pkg/core/messaging/persistmessage/message_service.go @@ -3,10 +3,12 @@ package persistmessage import ( "context" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" + uuid "github.com/satori/go.uuid" ) -type MessagePersistenceRepository interface { +type MessageService interface { Add(ctx context.Context, storeMessage *StoreMessage) error Update(ctx context.Context, storeMessage *StoreMessage) error ChangeState( @@ -22,4 +24,14 @@ type MessagePersistenceRepository interface { GetById(ctx context.Context, id uuid.UUID) (*StoreMessage, error) Remove(ctx context.Context, storeMessage *StoreMessage) (bool, error) CleanupMessages(ctx context.Context) error + Process(messageID string, ctx context.Context) error + ProcessAll(ctx context.Context) error + AddPublishMessage( + messageEnvelope types.MessageEnvelopeTMessage, + ctx context.Context, + ) error + AddReceivedMessage( + messageEnvelope types.MessageEnvelope, + ctx context.Context, + ) error } diff --git a/internal/pkg/core/messaging/persistmessage/store_message.go b/internal/pkg/core/messaging/persistmessage/store_message.go index 44ab41c0..8343df8f 100644 --- a/internal/pkg/core/messaging/persistmessage/store_message.go +++ b/internal/pkg/core/messaging/persistmessage/store_message.go @@ -25,7 +25,7 @@ type StoreMessage struct { ID uuid.UUID `gorm:"primaryKey"` DataType string Data string - Created time.Time + CreatedAt time.Time `gorm:"default:current_timestamp"` RetryCount int MessageStatus MessageStatus DeliveryType MessageDeliveryType @@ -41,7 +41,7 @@ func NewStoreMessage( ID: id, DataType: dataType, Data: data, - Created: time.Now(), + CreatedAt: time.Now(), MessageStatus: Stored, RetryCount: 0, DeliveryType: deliveryType, diff --git a/internal/pkg/core/messaging/types/message.go b/internal/pkg/core/messaging/types/message.go index 7203ffda..114b0b4b 100644 --- a/internal/pkg/core/messaging/types/message.go +++ b/internal/pkg/core/messaging/types/message.go @@ -2,14 +2,16 @@ package types import ( "time" + + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" ) type IMessage interface { GeMessageId() string GetCreated() time.Time - GetEventTypeName() string - SetEventTypeName(string) - IsMessage() bool + // GetMessageTypeName get short type name of the message - we use message short type name instead of full type name because this message in other receiver packages could have different package name + GetMessageTypeName() string + GetMessageFullTypeName() string } type Message struct { @@ -27,13 +29,6 @@ func NewMessageWithTypeName(messageId string, eventTypeName string) *Message { return &Message{MessageId: messageId, Created: time.Now(), EventType: eventTypeName} } -func (m *Message) IsMessage() bool { - if m == nil { - return false - } - return true -} - func (m *Message) GeMessageId() string { return m.MessageId } @@ -42,10 +37,10 @@ func (m *Message) GetCreated() time.Time { return m.Created } -func (m *Message) GetEventTypeName() string { - return m.EventType +func (m *Message) GetMessageTypeName() string { + return typeMapper.GetTypeName(m) } -func (m *Message) SetEventTypeName(eventTypeName string) { - m.EventType = eventTypeName +func (m *Message) GetMessageFullTypeName() string { + return typeMapper.GetFullTypeName(m) } diff --git a/internal/pkg/core/messaging/types/mock_IMessage_test.go b/internal/pkg/core/messaging/types/mock_IMessage_test.go index 0b1b265b..7f030c23 100644 --- a/internal/pkg/core/messaging/types/mock_IMessage_test.go +++ b/internal/pkg/core/messaging/types/mock_IMessage_test.go @@ -104,7 +104,7 @@ func (_c *MockIMessage_GetCreated_Call) RunAndReturn(run func() time.Time) *Mock } // GetEventTypeName provides a mock function with given fields: -func (_m *MockIMessage) GetEventTypeName() string { +func (_m *MockIMessage) GetMessageTypeName() string { ret := _m.Called() var r0 string @@ -117,14 +117,14 @@ func (_m *MockIMessage) GetEventTypeName() string { return r0 } -// MockIMessage_GetEventTypeName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEventTypeName' +// MockIMessage_GetEventTypeName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetMessageTypeName' type MockIMessage_GetEventTypeName_Call struct { *mock.Call } // GetEventTypeName is a helper method to define mock.On call func (_e *MockIMessage_Expecter) GetEventTypeName() *MockIMessage_GetEventTypeName_Call { - return &MockIMessage_GetEventTypeName_Call{Call: _e.mock.On("GetEventTypeName")} + return &MockIMessage_GetEventTypeName_Call{Call: _e.mock.On("GetMessageTypeName")} } func (_c *MockIMessage_GetEventTypeName_Call) Run(run func()) *MockIMessage_GetEventTypeName_Call { @@ -223,7 +223,8 @@ func (_c *MockIMessage_SetEventTypeName_Call) RunAndReturn(run func(string)) *Mo func NewMockIMessage(t interface { mock.TestingT Cleanup(func()) -}) *MockIMessage { +}, +) *MockIMessage { mock := &MockIMessage{} mock.Mock.Test(t) diff --git a/internal/pkg/core/mocks/EventSerializer.go b/internal/pkg/core/mocks/EventSerializer.go index 4cf217fa..c7de4adf 100644 --- a/internal/pkg/core/mocks/EventSerializer.go +++ b/internal/pkg/core/mocks/EventSerializer.go @@ -5,6 +5,8 @@ package mocks import ( reflect "reflect" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/contratcs" + mock "github.com/stretchr/testify/mock" serializer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" @@ -343,15 +345,15 @@ func (_c *EventSerializer_Serialize_Call) RunAndReturn(run func(interface{}) (*s } // Serializer provides a mock function with given fields: -func (_m *EventSerializer) Serializer() serializer.Serializer { +func (_m *EventSerializer) Serializer() contratcs.Serializer { ret := _m.Called() - var r0 serializer.Serializer - if rf, ok := ret.Get(0).(func() serializer.Serializer); ok { + var r0 contratcs.Serializer + if rf, ok := ret.Get(0).(func() contratcs.Serializer); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(serializer.Serializer) + r0 = ret.Get(0).(contratcs.Serializer) } } @@ -375,12 +377,12 @@ func (_c *EventSerializer_Serializer_Call) Run(run func()) *EventSerializer_Seri return _c } -func (_c *EventSerializer_Serializer_Call) Return(_a0 serializer.Serializer) *EventSerializer_Serializer_Call { +func (_c *EventSerializer_Serializer_Call) Return(_a0 contratcs.Serializer) *EventSerializer_Serializer_Call { _c.Call.Return(_a0) return _c } -func (_c *EventSerializer_Serializer_Call) RunAndReturn(run func() serializer.Serializer) *EventSerializer_Serializer_Call { +func (_c *EventSerializer_Serializer_Call) RunAndReturn(run func() contratcs.Serializer) *EventSerializer_Serializer_Call { _c.Call.Return(run) return _c } @@ -390,7 +392,8 @@ func (_c *EventSerializer_Serializer_Call) RunAndReturn(run func() serializer.Se func NewEventSerializer(t interface { mock.TestingT Cleanup(func()) -}) *EventSerializer { +}, +) *EventSerializer { mock := &EventSerializer{} mock.Mock.Test(t) diff --git a/internal/pkg/core/mocks/IDomainEvent.go b/internal/pkg/core/mocks/IDomainEvent.go index 72c220e3..b8a34b51 100644 --- a/internal/pkg/core/mocks/IDomainEvent.go +++ b/internal/pkg/core/mocks/IDomainEvent.go @@ -165,14 +165,14 @@ func (_m *IDomainEvent) GetEventType() string { return r0 } -// IDomainEvent_GetEventType_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEventType' +// IDomainEvent_GetEventType_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEventTypeName' type IDomainEvent_GetEventType_Call struct { *mock.Call } // GetEventType is a helper method to define mock.On call func (_e *IDomainEvent_Expecter) GetEventType() *IDomainEvent_GetEventType_Call { - return &IDomainEvent_GetEventType_Call{Call: _e.mock.On("GetEventType")} + return &IDomainEvent_GetEventType_Call{Call: _e.mock.On("GetEventTypeName")} } func (_c *IDomainEvent_GetEventType_Call) Run(run func()) *IDomainEvent_GetEventType_Call { @@ -283,7 +283,8 @@ func (_c *IDomainEvent_WithAggregate_Call) RunAndReturn(run func(uuid.UUID, int6 func NewIDomainEvent(t interface { mock.TestingT Cleanup(func()) -}) *IDomainEvent { +}, +) *IDomainEvent { mock := &IDomainEvent{} mock.Mock.Test(t) diff --git a/internal/pkg/core/mocks/IEvent.go b/internal/pkg/core/mocks/IEvent.go index 57d4e505..02f5c2a3 100644 --- a/internal/pkg/core/mocks/IEvent.go +++ b/internal/pkg/core/mocks/IEvent.go @@ -80,14 +80,14 @@ func (_m *IEvent) GetEventType() string { return r0 } -// IEvent_GetEventType_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEventType' +// IEvent_GetEventType_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEventTypeName' type IEvent_GetEventType_Call struct { *mock.Call } // GetEventType is a helper method to define mock.On call func (_e *IEvent_Expecter) GetEventType() *IEvent_GetEventType_Call { - return &IEvent_GetEventType_Call{Call: _e.mock.On("GetEventType")} + return &IEvent_GetEventType_Call{Call: _e.mock.On("GetEventTypeName")} } func (_c *IEvent_GetEventType_Call) Run(run func()) *IEvent_GetEventType_Call { @@ -153,7 +153,8 @@ func (_c *IEvent_GetOccurredOn_Call) RunAndReturn(run func() time.Time) *IEvent_ func NewIEvent(t interface { mock.TestingT Cleanup(func()) -}) *IEvent { +}, +) *IEvent { mock := &IEvent{} mock.Mock.Test(t) diff --git a/internal/pkg/core/serializer/contratcs/event_serializer.go b/internal/pkg/core/serializer/contratcs/event_serializer.go new file mode 100644 index 00000000..ce36a2f1 --- /dev/null +++ b/internal/pkg/core/serializer/contratcs/event_serializer.go @@ -0,0 +1,17 @@ +package contratcs + +import ( + "reflect" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/domain" +) + +type EventSerializer interface { + Serialize(event domain.IDomainEvent) (*EventSerializationResult, error) + SerializeObject(event interface{}) (*EventSerializationResult, error) + Deserialize(data []byte, eventType string, contentType string) (domain.IDomainEvent, error) + DeserializeObject(data []byte, eventType string, contentType string) (interface{}, error) + DeserializeType(data []byte, eventType reflect.Type, contentType string) (domain.IDomainEvent, error) + ContentType() string + Serializer() Serializer +} diff --git a/internal/pkg/core/serializer/contratcs/event_serrialization_result.go b/internal/pkg/core/serializer/contratcs/event_serrialization_result.go new file mode 100644 index 00000000..f528235a --- /dev/null +++ b/internal/pkg/core/serializer/contratcs/event_serrialization_result.go @@ -0,0 +1,6 @@ +package contratcs + +type EventSerializationResult struct { + Data []byte + ContentType string +} diff --git a/internal/pkg/core/serializer/contratcs/message_serializer.go b/internal/pkg/core/serializer/contratcs/message_serializer.go new file mode 100644 index 00000000..30682839 --- /dev/null +++ b/internal/pkg/core/serializer/contratcs/message_serializer.go @@ -0,0 +1,16 @@ +package contratcs + +import ( + "reflect" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" +) + +type MessageSerializer interface { + Serialize(message types.IMessage) (*EventSerializationResult, error) + Deserialize(data []byte, messageType string, contentType string) (types.IMessage, error) + DeserializeObject(data []byte, messageType string, contentType string) (interface{}, error) + DeserializeType(data []byte, messageType reflect.Type, contentType string) (types.IMessage, error) + ContentType() string + Serializer() Serializer +} diff --git a/internal/pkg/core/serializer/contratcs/metadata_serializer.go b/internal/pkg/core/serializer/contratcs/metadata_serializer.go new file mode 100644 index 00000000..7f3d3966 --- /dev/null +++ b/internal/pkg/core/serializer/contratcs/metadata_serializer.go @@ -0,0 +1,8 @@ +package contratcs + +import "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" + +type MetadataSerializer interface { + Serialize(meta metadata.Metadata) ([]byte, error) + Deserialize(bytes []byte) (metadata.Metadata, error) +} diff --git a/internal/pkg/core/serializer/serilizer.go b/internal/pkg/core/serializer/contratcs/serilizer.go similarity index 95% rename from internal/pkg/core/serializer/serilizer.go rename to internal/pkg/core/serializer/contratcs/serilizer.go index 47825d26..24e1651c 100644 --- a/internal/pkg/core/serializer/serilizer.go +++ b/internal/pkg/core/serializer/contratcs/serilizer.go @@ -1,4 +1,4 @@ -package serializer +package contratcs type Serializer interface { Marshal(v interface{}) ([]byte, error) diff --git a/internal/pkg/core/serializer/event_serializer.go b/internal/pkg/core/serializer/event_serializer.go deleted file mode 100644 index c7338d96..00000000 --- a/internal/pkg/core/serializer/event_serializer.go +++ /dev/null @@ -1,154 +0,0 @@ -package serializer - -import ( - "reflect" - - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/events" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" - - "emperror.dev/errors" -) - -type EventSerializer interface { - Serialize(event interface{}) (*EventSerializationResult, error) - Deserialize(data []byte, eventType string, contentType string) (interface{}, error) - DeserializeType(data []byte, eventType reflect.Type, contentType string) (interface{}, error) - DeserializeMessage(data []byte, eventType string, contentType string) (interface{}, error) - DeserializeEvent(data []byte, eventType string, contentType string) (interface{}, error) - ContentType() string - Serializer() Serializer -} - -type EventSerializationResult struct { - Data []byte - ContentType string -} - -type DefaultEventSerializer struct { - serializer Serializer -} - -func NewDefaultEventSerializer(serializer Serializer) EventSerializer { - return &DefaultEventSerializer{serializer: serializer} -} - -func (s *DefaultEventSerializer) Serializer() Serializer { - return s.serializer -} - -func (s *DefaultEventSerializer) Serialize( - event interface{}, -) (*EventSerializationResult, error) { - if event == nil { - return &EventSerializationResult{Data: nil, ContentType: s.ContentType()}, nil - } - - // here we just get type name instead of full type name - eventType := typeMapper.GetTypeName(event) - - data, err := s.serializer.Marshal(event) - if err != nil { - return nil, errors.WrapIff(err, "event.GetJsonData type: %s", eventType) - } - - result := &EventSerializationResult{Data: data, ContentType: s.ContentType()} - - return result, nil -} - -func (s *DefaultEventSerializer) Deserialize( - data []byte, - eventType string, - contentType string, -) (interface{}, error) { - if data == nil { - return nil, nil - } - - targetEventPointer := typeMapper.InstanceByTypeName(eventType) - - if contentType != s.ContentType() { - return nil, errors.Errorf("contentType: %s is not supported", contentType) - } - - if err := s.serializer.Unmarshal(data, targetEventPointer); err != nil { - return nil, errors.WrapIff(err, "event.GetJsonData type: %s", eventType) - } - - return targetEventPointer, nil -} - -func (s *DefaultEventSerializer) DeserializeType( - data []byte, - eventType reflect.Type, - contentType string, -) (interface{}, error) { - if data == nil { - return nil, nil - } - - targetEventPointer := typeMapper.InstanceByType(eventType) - - if contentType != s.ContentType() { - return nil, errors.Errorf("contentType: %s is not supported", contentType) - } - - if err := s.serializer.Unmarshal(data, targetEventPointer); err != nil { - return nil, errors.WrapIff(err, "event.GetJsonData type: %s", eventType) - } - - return targetEventPointer, nil -} - -func (s *DefaultEventSerializer) DeserializeMessage( - data []byte, - eventType string, - contentType string, -) (interface{}, error) { - if data == nil { - return nil, nil - } - - targetEventPointer := typeMapper.InstanceByTypeNameAndImplementedInterface[types.IMessage]( - eventType, - ) - - if contentType != s.ContentType() { - return nil, errors.Errorf("contentType: %s is not supported", contentType) - } - - if err := s.serializer.Unmarshal(data, targetEventPointer); err != nil { - return nil, errors.WrapIff(err, "event.GetJsonData type: %s", eventType) - } - - return targetEventPointer, nil -} - -func (s *DefaultEventSerializer) DeserializeEvent( - data []byte, - eventType string, - contentType string, -) (interface{}, error) { - if data == nil { - return nil, nil - } - - targetEventPointer := typeMapper.InstanceByTypeNameAndImplementedInterface[events.IEvent]( - eventType, - ) - - if contentType != s.ContentType() { - return nil, errors.Errorf("contentType: %s is not supported", contentType) - } - - if err := s.serializer.Unmarshal(data, targetEventPointer); err != nil { - return nil, errors.WrapIff(err, "event.GetJsonData type: %s", eventType) - } - - return targetEventPointer, nil -} - -func (s *DefaultEventSerializer) ContentType() string { - return "application/json" -} diff --git a/internal/pkg/core/serializer/json/event_serializer.go b/internal/pkg/core/serializer/json/event_serializer.go new file mode 100644 index 00000000..901a7f58 --- /dev/null +++ b/internal/pkg/core/serializer/json/event_serializer.go @@ -0,0 +1,134 @@ +package json + +import ( + "reflect" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/domain" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/contratcs" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" + + "emperror.dev/errors" +) + +type DefaultEventJsonSerializer struct { + serializer contratcs.Serializer +} + +func NewDefaultEventJsonSerializer(serializer contratcs.Serializer) contratcs.EventSerializer { + return &DefaultEventJsonSerializer{serializer: serializer} +} + +func (s *DefaultEventJsonSerializer) Serializer() contratcs.Serializer { + return s.serializer +} + +func (s *DefaultEventJsonSerializer) Serialize(event domain.IDomainEvent) (*contratcs.EventSerializationResult, error) { + return s.SerializeObject(event) +} + +func (s *DefaultEventJsonSerializer) SerializeObject(event interface{}) (*contratcs.EventSerializationResult, error) { + if event == nil { + return &contratcs.EventSerializationResult{Data: nil, ContentType: s.ContentType()}, nil + } + + // we use event short type name instead of full type name because this event in other receiver packages could have different package name + eventType := typeMapper.GetTypeName(event) + + data, err := s.serializer.Marshal(event) + if err != nil { + return nil, errors.WrapIff(err, "error in Marshaling: `%s`", eventType) + } + + result := &contratcs.EventSerializationResult{Data: data, ContentType: s.ContentType()} + + return result, nil +} + +func (s *DefaultEventJsonSerializer) Deserialize( + data []byte, + eventType string, + contentType string, +) (domain.IDomainEvent, error) { + if data == nil { + return nil, nil + } + + targetEventPointer := typeMapper.EmptyInstanceByTypeNameAndImplementedInterface[domain.IDomainEvent]( + eventType, + ) + + if targetEventPointer == nil { + return nil, errors.Errorf("event type `%s` is not impelemted IDomainEvent or can't be instansiated", eventType) + } + + if contentType != s.ContentType() { + return nil, errors.Errorf("contentType: %s is not supported", contentType) + } + + if err := s.serializer.Unmarshal(data, targetEventPointer); err != nil { + return nil, errors.WrapIff(err, "error in Unmarshaling: `%s`", eventType) + } + + return targetEventPointer.(domain.IDomainEvent), nil +} + +func (s *DefaultEventJsonSerializer) DeserializeObject( + data []byte, + eventType string, + contentType string, +) (interface{}, error) { + if data == nil { + return nil, nil + } + + targetEventPointer := typeMapper.InstanceByTypeName(eventType) + + if targetEventPointer == nil { + return nil, errors.Errorf("event type `%s` can't be instansiated", eventType) + } + + if contentType != s.ContentType() { + return nil, errors.Errorf("contentType: %s is not supported", contentType) + } + + if err := s.serializer.Unmarshal(data, targetEventPointer); err != nil { + return nil, errors.WrapIff(err, "error in Unmarshaling: `%s`", eventType) + } + + return targetEventPointer, nil +} + +func (s *DefaultEventJsonSerializer) DeserializeType( + data []byte, + eventType reflect.Type, + contentType string, +) (domain.IDomainEvent, error) { + if data == nil { + return nil, nil + } + + // we use event short type name instead of full type name because this event in other receiver packages could have different package name + eventTypeName := typeMapper.GetTypeName(eventType) + + targetEventPointer := typeMapper.EmptyInstanceByTypeNameAndImplementedInterface[domain.IDomainEvent]( + eventTypeName, + ) + + if targetEventPointer == nil { + return nil, errors.Errorf("event type `%s` is not impelemted IDomainEvent or can't be instansiated", eventType) + } + + if contentType != s.ContentType() { + return nil, errors.Errorf("contentType: %s is not supported", contentType) + } + + if err := s.serializer.Unmarshal(data, targetEventPointer); err != nil { + return nil, errors.WrapIff(err, "error in Unmarshaling: `%s`", eventType) + } + + return targetEventPointer.(domain.IDomainEvent), nil +} + +func (s *DefaultEventJsonSerializer) ContentType() string { + return "application/json" +} diff --git a/internal/pkg/core/serializer/json/json_serializer.go b/internal/pkg/core/serializer/json/json_serializer.go index 16018f86..930260f0 100644 --- a/internal/pkg/core/serializer/json/json_serializer.go +++ b/internal/pkg/core/serializer/json/json_serializer.go @@ -3,7 +3,7 @@ package json import ( "log" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/contratcs" "github.com/TylerBrock/colorjson" "github.com/goccy/go-json" @@ -12,7 +12,7 @@ import ( type jsonSerializer struct{} -func NewDefaultSerializer() serializer.Serializer { +func NewDefaultJsonSerializer() contratcs.Serializer { return &jsonSerializer{} } diff --git a/internal/pkg/core/serializer/json/json_serilizer_test.go b/internal/pkg/core/serializer/json/json_serilizer_test.go index 6c35f431..3877cb6e 100644 --- a/internal/pkg/core/serializer/json/json_serilizer_test.go +++ b/internal/pkg/core/serializer/json/json_serilizer_test.go @@ -1,3 +1,6 @@ +//go:build unit +// +build unit + package json import ( @@ -12,7 +15,7 @@ type person struct { Age int } -var currentSerializer = NewDefaultSerializer() +var currentSerializer = NewDefaultJsonSerializer() func Test_Deserialize_Unstructured_Data_Into_Empty_Interface(t *testing.T) { // https://www.sohamkamani.com/golang/json/#decoding-json-to-maps---unstructured-data diff --git a/internal/pkg/core/serializer/json/message_serializer.go b/internal/pkg/core/serializer/json/message_serializer.go new file mode 100644 index 00000000..a5b981cc --- /dev/null +++ b/internal/pkg/core/serializer/json/message_serializer.go @@ -0,0 +1 @@ +package json diff --git a/internal/pkg/core/serializer/json/metadata_serializer.go b/internal/pkg/core/serializer/json/metadata_serializer.go new file mode 100644 index 00000000..5f9f648c --- /dev/null +++ b/internal/pkg/core/serializer/json/metadata_serializer.go @@ -0,0 +1,44 @@ +package json + +import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/contratcs" + + "emperror.dev/errors" +) + +type DefaultMetadataJsonSerializer struct { + serializer contratcs.Serializer +} + +func NewDefaultMetadataJsonSerializer(serializer contratcs.Serializer) contratcs.MetadataSerializer { + return &DefaultMetadataJsonSerializer{serializer: serializer} +} + +func (s *DefaultMetadataJsonSerializer) Serialize(meta metadata.Metadata) ([]byte, error) { + if meta == nil { + return nil, nil + } + + marshal, err := s.serializer.Marshal(meta) + if err != nil { + return nil, errors.WrapIf(err, "failed to marshal metadata") + } + + return marshal, nil +} + +func (s *DefaultMetadataJsonSerializer) Deserialize(bytes []byte) (metadata.Metadata, error) { + if bytes == nil { + return nil, nil + } + + var meta metadata.Metadata + + err := s.serializer.Unmarshal(bytes, &meta) + if err != nil { + return nil, errors.WrapIf(err, "failed to unmarshal metadata") + } + + return meta, nil +} diff --git a/internal/pkg/core/serializer/metadata_serializer.go b/internal/pkg/core/serializer/metadata_serializer.go deleted file mode 100644 index 4c75ee8a..00000000 --- a/internal/pkg/core/serializer/metadata_serializer.go +++ /dev/null @@ -1,48 +0,0 @@ -package serializer - -import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" - - "emperror.dev/errors" -) - -type MetadataSerializer interface { - Serialize(meta metadata.Metadata) ([]byte, error) - Deserialize(bytes []byte) (metadata.Metadata, error) -} - -type DefaultMetadataSerializer struct { - serializer Serializer -} - -func NewDefaultMetadataSerializer(serializer Serializer) MetadataSerializer { - return &DefaultMetadataSerializer{serializer: serializer} -} - -func (s *DefaultMetadataSerializer) Serialize(meta metadata.Metadata) ([]byte, error) { - if meta == nil { - return nil, nil - } - - marshal, err := s.serializer.Marshal(meta) - if err != nil { - return nil, errors.WrapIf(err, "failed to marshal metadata") - } - - return marshal, nil -} - -func (s *DefaultMetadataSerializer) Deserialize(bytes []byte) (metadata.Metadata, error) { - if bytes == nil { - return nil, nil - } - - var meta metadata.Metadata - - err := s.serializer.Unmarshal(bytes, &meta) - if err != nil { - return nil, errors.WrapIf(err, "failed to unmarshal metadata") - } - - return meta, nil -} diff --git a/internal/pkg/es/errors/errors.go b/internal/pkg/es/errors/errors.go index 4a2980c1..e431daf4 100644 --- a/internal/pkg/es/errors/errors.go +++ b/internal/pkg/es/errors/errors.go @@ -3,7 +3,7 @@ package errors import ( "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "emperror.dev/errors" ) diff --git a/internal/pkg/eventstroredb/errors/aggregate_not_found_error.go b/internal/pkg/eventstroredb/errors/aggregate_not_found_error.go index 54f4da05..2d8b089d 100644 --- a/internal/pkg/eventstroredb/errors/aggregate_not_found_error.go +++ b/internal/pkg/eventstroredb/errors/aggregate_not_found_error.go @@ -3,7 +3,7 @@ package errors import ( "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "emperror.dev/errors" uuid "github.com/satori/go.uuid" diff --git a/internal/pkg/eventstroredb/errors/append_to_stream_error.go b/internal/pkg/eventstroredb/errors/append_to_stream_error.go index bb40ca1f..060b3a16 100644 --- a/internal/pkg/eventstroredb/errors/append_to_stream_error.go +++ b/internal/pkg/eventstroredb/errors/append_to_stream_error.go @@ -3,7 +3,7 @@ package errors import ( "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "emperror.dev/errors" ) diff --git a/internal/pkg/eventstroredb/errors/delete_stream_error.go b/internal/pkg/eventstroredb/errors/delete_stream_error.go index 5e840f62..8d93cd58 100644 --- a/internal/pkg/eventstroredb/errors/delete_stream_error.go +++ b/internal/pkg/eventstroredb/errors/delete_stream_error.go @@ -3,7 +3,7 @@ package errors import ( "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "emperror.dev/errors" ) diff --git a/internal/pkg/eventstroredb/errors/read_stream_error.go b/internal/pkg/eventstroredb/errors/read_stream_error.go index 3ea35e12..68d0b7cb 100644 --- a/internal/pkg/eventstroredb/errors/read_stream_error.go +++ b/internal/pkg/eventstroredb/errors/read_stream_error.go @@ -1,7 +1,7 @@ package errors import ( - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "emperror.dev/errors" ) diff --git a/internal/pkg/eventstroredb/errors/stream_not_found_error.go b/internal/pkg/eventstroredb/errors/stream_not_found_error.go index e9d2d45c..d89d42a2 100644 --- a/internal/pkg/eventstroredb/errors/stream_not_found_error.go +++ b/internal/pkg/eventstroredb/errors/stream_not_found_error.go @@ -3,7 +3,7 @@ package errors import ( "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "emperror.dev/errors" ) diff --git a/internal/pkg/eventstroredb/errors/truncate_stream_error.go b/internal/pkg/eventstroredb/errors/truncate_stream_error.go index 479f7a39..13c8edc8 100644 --- a/internal/pkg/eventstroredb/errors/truncate_stream_error.go +++ b/internal/pkg/eventstroredb/errors/truncate_stream_error.go @@ -3,7 +3,7 @@ package errors import ( "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "emperror.dev/errors" ) diff --git a/internal/pkg/eventstroredb/esdb_serilizer.go b/internal/pkg/eventstroredb/esdb_serilizer.go index 2de85f15..a5cb1910 100644 --- a/internal/pkg/eventstroredb/esdb_serilizer.go +++ b/internal/pkg/eventstroredb/esdb_serilizer.go @@ -6,7 +6,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/domain" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/contratcs" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/models" appendResult "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/models/append_result" readPosition "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/models/stream_position/read_position" @@ -23,13 +23,13 @@ import ( ) type EsdbSerializer struct { - metadataSerializer serializer.MetadataSerializer - eventSerializer serializer.EventSerializer + metadataSerializer contratcs.MetadataSerializer + eventSerializer contratcs.EventSerializer } func NewEsdbSerializer( - metadataSerializer serializer.MetadataSerializer, - eventSerializer serializer.EventSerializer, + metadataSerializer contratcs.MetadataSerializer, + eventSerializer contratcs.EventSerializer, ) *EsdbSerializer { return &EsdbSerializer{ metadataSerializer: metadataSerializer, @@ -139,7 +139,7 @@ func (e *EsdbSerializer) EsdbPositionToStreamReadPosition( func (e *EsdbSerializer) ResolvedEventToStreamEvent( resolveEvent *esdb.ResolvedEvent, ) (*models.StreamEvent, error) { - deserializedEvent, err := e.eventSerializer.DeserializeEvent( + deserializedEvent, err := e.eventSerializer.Deserialize( resolveEvent.Event.Data, resolveEvent.Event.EventType, resolveEvent.Event.ContentType, @@ -160,7 +160,7 @@ func (e *EsdbSerializer) ResolvedEventToStreamEvent( return &models.StreamEvent{ EventID: id, - Event: deserializedEvent.(domain.IDomainEvent), + Event: deserializedEvent, Metadata: deserializedMeta, Version: int64(resolveEvent.Event.EventNumber), Position: e.EsdbPositionToStreamReadPosition(resolveEvent.OriginalEvent().Position).Value(), @@ -192,6 +192,30 @@ func (e *EsdbSerializer) EsdbWriteResultToAppendEventResult( } func (e *EsdbSerializer) Serialize( + data domain.IDomainEvent, + meta metadata.Metadata, +) (*esdb.EventData, error) { + serializedData, err := e.eventSerializer.Serialize(data) + if err != nil { + return nil, err + } + + serializedMeta, err := e.metadataSerializer.Serialize(meta) + if err != nil { + return nil, err + } + + id, err := uuid.NewV4() + return &esdb.EventData{ + EventID: id, + EventType: typeMapper.GetTypeName(data), + Data: serializedData.Data, + ContentType: esdb.JsonContentType, + Metadata: serializedMeta, + }, nil +} + +func (e *EsdbSerializer) SerializeObject( data interface{}, meta metadata.Metadata, ) (*esdb.EventData, error) { @@ -217,12 +241,36 @@ func (e *EsdbSerializer) Serialize( func (e *EsdbSerializer) Deserialize( resolveEvent *esdb.ResolvedEvent, +) (domain.IDomainEvent, metadata.Metadata, error) { + eventType := resolveEvent.Event.EventType + data := resolveEvent.Event.Data + userMeta := resolveEvent.Event.UserMetadata + + payload, err := e.eventSerializer.Deserialize( + data, + eventType, + resolveEvent.Event.ContentType, + ) + if err != nil { + return nil, nil, err + } + + meta, err := e.metadataSerializer.Deserialize(userMeta) + if err != nil { + return nil, nil, err + } + + return payload, meta, nil +} + +func (e *EsdbSerializer) DeserializeObject( + resolveEvent *esdb.ResolvedEvent, ) (interface{}, metadata.Metadata, error) { eventType := resolveEvent.Event.EventType data := resolveEvent.Event.Data userMeta := resolveEvent.Event.UserMetadata - payload, err := e.eventSerializer.DeserializeEvent( + payload, err := e.eventSerializer.Deserialize( data, eventType, resolveEvent.Event.ContentType, diff --git a/internal/pkg/eventstroredb/esdb_subscription_check_point_repository.go b/internal/pkg/eventstroredb/esdb_subscription_check_point_repository.go index 739b5321..ebcf09ad 100644 --- a/internal/pkg/eventstroredb/esdb_subscription_check_point_repository.go +++ b/internal/pkg/eventstroredb/esdb_subscription_check_point_repository.go @@ -71,7 +71,7 @@ func (e *esdbSubscriptionCheckpointRepository) Load( return 0, errors.WrapIf(err, "stream.Recv") } - deserialized, _, err := e.esdbSerilizer.Deserialize(event) + deserialized, _, err := e.esdbSerilizer.DeserializeObject(event) if err != nil { return 0, err } diff --git a/internal/pkg/eventstroredb/event_store.go b/internal/pkg/eventstroredb/event_store.go index f2b1e57c..d6bf7049 100644 --- a/internal/pkg/eventstroredb/event_store.go +++ b/internal/pkg/eventstroredb/event_store.go @@ -68,7 +68,7 @@ func (e *eventStoreDbEventStore) StreamExists( span, errors.WithMessage( esErrors.NewReadStreamError(err), - "[eventStoreDbEventStore_StreamExists:ReadStream] error in reading stream", + "error in reading stream", ), ) } @@ -113,7 +113,7 @@ func (e *eventStoreDbEventStore) AppendEvents( span, errors.WithMessage( esErrors.NewAppendToStreamError(err, streamName.String()), - "[eventStoreDbEventStore_AppendEvents:AppendToStream] error in appending to stream", + "error in appending to stream", ), ) } @@ -125,7 +125,7 @@ func (e *eventStoreDbEventStore) AppendEvents( ) e.log.Infow( - "[eventStoreDbEventStore_AppendEvents] events append to stream successfully", + "events append to stream successfully", logger.Fields{ "AppendEventsResult": appendEventsResult, "StreamId": streamName.String(), @@ -155,7 +155,7 @@ func (e *eventStoreDbEventStore) AppendNewEvents( span, errors.WithMessage( esErrors.NewAppendToStreamError(err, streamName.String()), - "[eventStoreDbEventStore_AppendNewEvents:AppendEvents] error in appending to stream", + "error in appending to stream", ), ) } @@ -163,7 +163,7 @@ func (e *eventStoreDbEventStore) AppendNewEvents( span.SetAttributes(attribute.Object("AppendNewEvents", appendEventsResult)) e.log.Infow( - "[eventStoreDbEventStore_AppendNewEvents] events append to stream successfully", + "events append to stream successfully", logger.Fields{ "AppendEventsResult": appendEventsResult, "StreamId": streamName.String(), @@ -199,7 +199,7 @@ func (e *eventStoreDbEventStore) ReadEvents( span, errors.WithMessage( esErrors.NewReadStreamError(err), - "[eventStoreDbEventStore_ReadEvents:ReadStream] error in reading stream", + "error in reading stream", ), ) } @@ -214,7 +214,7 @@ func (e *eventStoreDbEventStore) ReadEvents( span, errors.WrapIf( err, - "[eventStoreDbEventStore_ReadEvents.EsdbReadStreamToResolvedEvents] error in converting to resolved events", + "error in converting to resolved events", ), ) } @@ -225,7 +225,7 @@ func (e *eventStoreDbEventStore) ReadEvents( span, errors.WrapIf( err, - "[eventStoreDbEventStore_ReadEvents.ResolvedEventsToStreamEvents] error in converting to stream events", + "error in converting to stream events", ), ) } @@ -389,7 +389,7 @@ func (e *eventStoreDbEventStore) TruncateStream( span, errors.WithMessage( esErrors.NewTruncateStreamError(err, streamName.String()), - "[eventStoreDbEventStore_TruncateStream:SetStreamMetadata] error in truncating stream", + "error in truncating stream", ), ) } @@ -398,7 +398,7 @@ func (e *eventStoreDbEventStore) TruncateStream( e.log.Infow( fmt.Sprintf( - "[eventStoreDbEventStore.TruncateStream] stream with id %s truncated successfully", + "stream with id %s truncated successfully", streamName.String(), ), logger.Fields{ @@ -432,7 +432,7 @@ func (e *eventStoreDbEventStore) DeleteStream( span, errors.WithMessage( esErrors.NewDeleteStreamError(err, streamName.String()), - "[eventStoreDbEventStore_DeleteStream:DeleteStream] error in deleting stream", + "error in deleting stream", ), ) } @@ -441,7 +441,7 @@ func (e *eventStoreDbEventStore) DeleteStream( e.log.Infow( fmt.Sprintf( - "[eventStoreDbEventStore.DeleteStream] stream with id %s deleted successfully", + "stream with id %s deleted successfully", streamName.String(), ), logger.Fields{ diff --git a/internal/pkg/grpc/grpcErrors/custom_grpc_errors.go b/internal/pkg/grpc/grpcerrors/custom_grpc_errors.go similarity index 99% rename from internal/pkg/grpc/grpcErrors/custom_grpc_errors.go rename to internal/pkg/grpc/grpcerrors/custom_grpc_errors.go index f28fd4af..cd1066f5 100644 --- a/internal/pkg/grpc/grpcErrors/custom_grpc_errors.go +++ b/internal/pkg/grpc/grpcerrors/custom_grpc_errors.go @@ -1,4 +1,4 @@ -package grpcErrors +package grpcerrors import ( "time" diff --git a/internal/pkg/grpc/grpcErrors/grpc_error_parser.go b/internal/pkg/grpc/grpcerrors/grpc_error_parser.go similarity index 96% rename from internal/pkg/grpc/grpcErrors/grpc_error_parser.go rename to internal/pkg/grpc/grpcerrors/grpc_error_parser.go index be8a55d4..d951ae45 100644 --- a/internal/pkg/grpc/grpcErrors/grpc_error_parser.go +++ b/internal/pkg/grpc/grpcerrors/grpc_error_parser.go @@ -1,12 +1,12 @@ -package grpcErrors +package grpcerrors import ( "context" "database/sql" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/constants" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" + errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/errorutils" "emperror.dev/errors" "github.com/go-playground/validator" diff --git a/internal/pkg/grpc/grpcErrors/grpc_errors.go b/internal/pkg/grpc/grpcerrors/grpc_errors.go similarity index 99% rename from internal/pkg/grpc/grpcErrors/grpc_errors.go rename to internal/pkg/grpc/grpcerrors/grpc_errors.go index 2d4f41aa..1e62d063 100644 --- a/internal/pkg/grpc/grpcErrors/grpc_errors.go +++ b/internal/pkg/grpc/grpcerrors/grpc_errors.go @@ -1,4 +1,4 @@ -package grpcErrors +package grpcerrors import ( "encoding/json" diff --git a/internal/pkg/grpc/interceptors/grpc_error/error_interceptor.go b/internal/pkg/grpc/interceptors/grpcerror/error_interceptor.go similarity index 87% rename from internal/pkg/grpc/interceptors/grpc_error/error_interceptor.go rename to internal/pkg/grpc/interceptors/grpcerror/error_interceptor.go index 3f267c71..aa23aef0 100644 --- a/internal/pkg/grpc/interceptors/grpc_error/error_interceptor.go +++ b/internal/pkg/grpc/interceptors/grpcerror/error_interceptor.go @@ -3,7 +3,7 @@ package grpcError import ( "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/grpcErrors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/grpcerrors" "emperror.dev/errors" "google.golang.org/grpc" @@ -19,11 +19,11 @@ func UnaryServerInterceptor() grpc.UnaryServerInterceptor { ) (interface{}, error) { resp, err := handler(ctx, req) - var grpcErr grpcErrors.GrpcErr + var grpcErr grpcerrors.GrpcErr // if error was not `grpcErr` we will convert the error to a `grpcErr` if ok := errors.As(err, &grpcErr); !ok { - grpcErr = grpcErrors.ParseError(err) + grpcErr = grpcerrors.ParseError(err) } if grpcErr != nil { @@ -44,11 +44,11 @@ func StreamServerInterceptor() grpc.StreamServerInterceptor { ) error { err := handler(srv, ss) - var grpcErr grpcErrors.GrpcErr + var grpcErr grpcerrors.GrpcErr // if error was not `grpcErr` we will convert the error to a `grpcErr` if ok := errors.As(err, &grpcErr); !ok { - grpcErr = grpcErrors.ParseError(err) + grpcErr = grpcerrors.ParseError(err) } if grpcErr != nil { diff --git a/internal/pkg/grpc/server.go b/internal/pkg/grpc/server.go index 98c0cce3..78a8ece2 100644 --- a/internal/pkg/grpc/server.go +++ b/internal/pkg/grpc/server.go @@ -7,7 +7,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/handlers/otel" - grpcError "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/interceptors/grpc_error" + grpcError "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/interceptors/grpcerror" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "emperror.dev/errors" diff --git a/internal/pkg/health/health_endpoint.go b/internal/pkg/health/health_endpoint.go index 75a10fcd..20fe7363 100644 --- a/internal/pkg/health/health_endpoint.go +++ b/internal/pkg/health/health_endpoint.go @@ -4,7 +4,7 @@ import ( "net/http" contracts2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health/contracts" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/contracts" "github.com/labstack/echo/v4" ) diff --git a/internal/pkg/http/custom_echo/config/echo_http_options.go b/internal/pkg/http/customecho/config/echo_http_options.go similarity index 100% rename from internal/pkg/http/custom_echo/config/echo_http_options.go rename to internal/pkg/http/customecho/config/echo_http_options.go diff --git a/internal/pkg/http/custom_echo/contracts/echoserver.go b/internal/pkg/http/customecho/contracts/echoserver.go similarity index 96% rename from internal/pkg/http/custom_echo/contracts/echoserver.go rename to internal/pkg/http/customecho/contracts/echoserver.go index a53f95ef..bc4d22cf 100644 --- a/internal/pkg/http/custom_echo/contracts/echoserver.go +++ b/internal/pkg/http/customecho/contracts/echoserver.go @@ -3,7 +3,7 @@ package contracts import ( "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/labstack/echo/v4" diff --git a/internal/pkg/http/custom_echo/contracts/route_builder.go b/internal/pkg/http/customecho/contracts/route_builder.go similarity index 100% rename from internal/pkg/http/custom_echo/contracts/route_builder.go rename to internal/pkg/http/customecho/contracts/route_builder.go diff --git a/internal/pkg/http/custom_echo/custom_echo_fx.go b/internal/pkg/http/customecho/custom_echo_fx.go similarity index 98% rename from internal/pkg/http/custom_echo/custom_echo_fx.go rename to internal/pkg/http/customecho/custom_echo_fx.go index a73fa406..d0baf920 100644 --- a/internal/pkg/http/custom_echo/custom_echo_fx.go +++ b/internal/pkg/http/customecho/custom_echo_fx.go @@ -5,8 +5,8 @@ import ( "errors" "net/http" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "go.uber.org/fx" diff --git a/internal/pkg/http/custom_echo/echo_server.go b/internal/pkg/http/customecho/echo_server.go similarity index 92% rename from internal/pkg/http/custom_echo/echo_server.go rename to internal/pkg/http/customecho/echo_server.go index 384878d3..83b25d98 100644 --- a/internal/pkg/http/custom_echo/echo_server.go +++ b/internal/pkg/http/customecho/echo_server.go @@ -6,14 +6,14 @@ import ( "strings" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/constants" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/config" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" - hadnlers "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/hadnlers" - ipratelimit "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/middlewares/ip_ratelimit" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/middlewares/log" - otelMetrics "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/middlewares/otel_metrics" - oteltracing "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/middlewares/otel_tracing" - problemdetail "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/middlewares/problem_detail" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/contracts" + hadnlers "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/hadnlers" + ipratelimit "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/middlewares/ip_ratelimit" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/middlewares/log" + otelMetrics "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/middlewares/otel_metrics" + oteltracing "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/middlewares/otel_tracing" + problemdetail "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/middlewares/problem_detail" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/labstack/echo/v4" diff --git a/internal/pkg/http/custom_echo/hadnlers/problemdetail_error_handler.go b/internal/pkg/http/customecho/hadnlers/problemdetail_error_handler.go similarity index 86% rename from internal/pkg/http/custom_echo/hadnlers/problemdetail_error_handler.go rename to internal/pkg/http/customecho/hadnlers/problemdetail_error_handler.go index 2cbbeab2..bc291f20 100644 --- a/internal/pkg/http/custom_echo/hadnlers/problemdetail_error_handler.go +++ b/internal/pkg/http/customecho/hadnlers/problemdetail_error_handler.go @@ -1,7 +1,7 @@ package handlers import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/problemDetails" + problemDetails "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/problemdetails" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "emperror.dev/errors" diff --git a/internal/pkg/http/custom_echo/middlewares/ip_ratelimit/config.go b/internal/pkg/http/customecho/middlewares/ip_ratelimit/config.go similarity index 100% rename from internal/pkg/http/custom_echo/middlewares/ip_ratelimit/config.go rename to internal/pkg/http/customecho/middlewares/ip_ratelimit/config.go diff --git a/internal/pkg/http/custom_echo/middlewares/ip_ratelimit/ip_ratelimit.go b/internal/pkg/http/customecho/middlewares/ip_ratelimit/ip_ratelimit.go similarity index 100% rename from internal/pkg/http/custom_echo/middlewares/ip_ratelimit/ip_ratelimit.go rename to internal/pkg/http/customecho/middlewares/ip_ratelimit/ip_ratelimit.go diff --git a/internal/pkg/http/custom_echo/middlewares/log/config.go b/internal/pkg/http/customecho/middlewares/log/config.go similarity index 100% rename from internal/pkg/http/custom_echo/middlewares/log/config.go rename to internal/pkg/http/customecho/middlewares/log/config.go diff --git a/internal/pkg/http/custom_echo/middlewares/log/log_middleware.go b/internal/pkg/http/customecho/middlewares/log/log_middleware.go similarity index 100% rename from internal/pkg/http/custom_echo/middlewares/log/log_middleware.go rename to internal/pkg/http/customecho/middlewares/log/log_middleware.go diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/config.go b/internal/pkg/http/customecho/middlewares/otel_metrics/config.go similarity index 100% rename from internal/pkg/http/custom_echo/middlewares/otel_metrics/config.go rename to internal/pkg/http/customecho/middlewares/otel_metrics/config.go diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/metric.go b/internal/pkg/http/customecho/middlewares/otel_metrics/metric.go similarity index 100% rename from internal/pkg/http/custom_echo/middlewares/otel_metrics/metric.go rename to internal/pkg/http/customecho/middlewares/otel_metrics/metric.go diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/metrics_middleware.go b/internal/pkg/http/customecho/middlewares/otel_metrics/metrics_middleware.go similarity index 100% rename from internal/pkg/http/custom_echo/middlewares/otel_metrics/metrics_middleware.go rename to internal/pkg/http/customecho/middlewares/otel_metrics/metrics_middleware.go diff --git a/internal/pkg/http/custom_echo/middlewares/otel_metrics/view.go b/internal/pkg/http/customecho/middlewares/otel_metrics/view.go similarity index 100% rename from internal/pkg/http/custom_echo/middlewares/otel_metrics/view.go rename to internal/pkg/http/customecho/middlewares/otel_metrics/view.go diff --git a/internal/pkg/http/custom_echo/middlewares/otel_tracing/config.go b/internal/pkg/http/customecho/middlewares/otel_tracing/config.go similarity index 100% rename from internal/pkg/http/custom_echo/middlewares/otel_tracing/config.go rename to internal/pkg/http/customecho/middlewares/otel_tracing/config.go diff --git a/internal/pkg/http/custom_echo/middlewares/otel_tracing/tracing_middleware.go b/internal/pkg/http/customecho/middlewares/otel_tracing/tracing_middleware.go similarity index 100% rename from internal/pkg/http/custom_echo/middlewares/otel_tracing/tracing_middleware.go rename to internal/pkg/http/customecho/middlewares/otel_tracing/tracing_middleware.go diff --git a/internal/pkg/http/custom_echo/middlewares/problem_detail/config.go b/internal/pkg/http/customecho/middlewares/problem_detail/config.go similarity index 83% rename from internal/pkg/http/custom_echo/middlewares/problem_detail/config.go rename to internal/pkg/http/customecho/middlewares/problem_detail/config.go index 715133a7..27fcbc3c 100644 --- a/internal/pkg/http/custom_echo/middlewares/problem_detail/config.go +++ b/internal/pkg/http/customecho/middlewares/problem_detail/config.go @@ -1,7 +1,7 @@ package problemdetail import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/problemDetails" + problemDetails "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/problemdetails" "github.com/labstack/echo/v4/middleware" ) diff --git a/internal/pkg/http/custom_echo/middlewares/problem_detail/problem_detail_middleware.go b/internal/pkg/http/customecho/middlewares/problem_detail/problem_detail_middleware.go similarity index 89% rename from internal/pkg/http/custom_echo/middlewares/problem_detail/problem_detail_middleware.go rename to internal/pkg/http/customecho/middlewares/problem_detail/problem_detail_middleware.go index 829548d9..9db974a1 100644 --- a/internal/pkg/http/custom_echo/middlewares/problem_detail/problem_detail_middleware.go +++ b/internal/pkg/http/customecho/middlewares/problem_detail/problem_detail_middleware.go @@ -1,7 +1,7 @@ package problemdetail import ( - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/problemDetails" + problemDetails "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/problemdetails" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" diff --git a/internal/pkg/http/http_fx.go b/internal/pkg/http/http_fx.go index c2f9334a..20ba60cb 100644 --- a/internal/pkg/http/http_fx.go +++ b/internal/pkg/http/http_fx.go @@ -2,7 +2,7 @@ package http import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/client" - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho" "go.uber.org/fx" ) diff --git a/internal/pkg/http/http_errors/contracts/contracts.go b/internal/pkg/http/httperrors/contracts/contracts.go similarity index 100% rename from internal/pkg/http/http_errors/contracts/contracts.go rename to internal/pkg/http/httperrors/contracts/contracts.go diff --git a/internal/pkg/http/http_errors/custom_errors/api_error.go b/internal/pkg/http/httperrors/customerrors/api_error.go similarity index 100% rename from internal/pkg/http/http_errors/custom_errors/api_error.go rename to internal/pkg/http/httperrors/customerrors/api_error.go diff --git a/internal/pkg/http/http_errors/custom_errors/application_error.go b/internal/pkg/http/httperrors/customerrors/application_error.go similarity index 100% rename from internal/pkg/http/http_errors/custom_errors/application_error.go rename to internal/pkg/http/httperrors/customerrors/application_error.go diff --git a/internal/pkg/http/http_errors/custom_errors/bad_request_error.go b/internal/pkg/http/httperrors/customerrors/bad_request_error.go similarity index 100% rename from internal/pkg/http/http_errors/custom_errors/bad_request_error.go rename to internal/pkg/http/httperrors/customerrors/bad_request_error.go diff --git a/internal/pkg/http/http_errors/custom_errors/conflict_error.go b/internal/pkg/http/httperrors/customerrors/conflict_error.go similarity index 100% rename from internal/pkg/http/http_errors/custom_errors/conflict_error.go rename to internal/pkg/http/httperrors/customerrors/conflict_error.go diff --git a/internal/pkg/http/http_errors/custom_errors/custom_errors.go b/internal/pkg/http/httperrors/customerrors/custom_errors.go similarity index 98% rename from internal/pkg/http/http_errors/custom_errors/custom_errors.go rename to internal/pkg/http/httperrors/customerrors/custom_errors.go index a7a0d6c7..58d51b46 100644 --- a/internal/pkg/http/http_errors/custom_errors/custom_errors.go +++ b/internal/pkg/http/httperrors/customerrors/custom_errors.go @@ -4,7 +4,7 @@ import ( "fmt" "io" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/contracts" "emperror.dev/errors" ) diff --git a/internal/pkg/http/http_errors/custom_errors/custom_errors_test.go b/internal/pkg/http/httperrors/customerrors/custom_errors_test.go similarity index 99% rename from internal/pkg/http/http_errors/custom_errors/custom_errors_test.go rename to internal/pkg/http/httperrors/customerrors/custom_errors_test.go index 1298aded..60985897 100644 --- a/internal/pkg/http/http_errors/custom_errors/custom_errors_test.go +++ b/internal/pkg/http/httperrors/customerrors/custom_errors_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/contracts" - errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/contracts" + errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/errorutils" "emperror.dev/errors" "github.com/stretchr/testify/assert" diff --git a/internal/pkg/http/http_errors/custom_errors/domain_error.go b/internal/pkg/http/httperrors/customerrors/domain_error.go similarity index 100% rename from internal/pkg/http/http_errors/custom_errors/domain_error.go rename to internal/pkg/http/httperrors/customerrors/domain_error.go diff --git a/internal/pkg/http/http_errors/custom_errors/forbiden_error.go b/internal/pkg/http/httperrors/customerrors/forbiden_error.go similarity index 100% rename from internal/pkg/http/http_errors/custom_errors/forbiden_error.go rename to internal/pkg/http/httperrors/customerrors/forbiden_error.go diff --git a/internal/pkg/http/http_errors/custom_errors/internal_server_error.go b/internal/pkg/http/httperrors/customerrors/internal_server_error.go similarity index 100% rename from internal/pkg/http/http_errors/custom_errors/internal_server_error.go rename to internal/pkg/http/httperrors/customerrors/internal_server_error.go diff --git a/internal/pkg/http/http_errors/custom_errors/marshaling_error.go b/internal/pkg/http/httperrors/customerrors/marshaling_error.go similarity index 100% rename from internal/pkg/http/http_errors/custom_errors/marshaling_error.go rename to internal/pkg/http/httperrors/customerrors/marshaling_error.go diff --git a/internal/pkg/http/http_errors/custom_errors/not_found_error.go b/internal/pkg/http/httperrors/customerrors/not_found_error.go similarity index 100% rename from internal/pkg/http/http_errors/custom_errors/not_found_error.go rename to internal/pkg/http/httperrors/customerrors/not_found_error.go diff --git a/internal/pkg/http/http_errors/custom_errors/unauthorized_error.go b/internal/pkg/http/httperrors/customerrors/unauthorized_error.go similarity index 100% rename from internal/pkg/http/http_errors/custom_errors/unauthorized_error.go rename to internal/pkg/http/httperrors/customerrors/unauthorized_error.go diff --git a/internal/pkg/http/http_errors/custom_errors/unmarshaling_error.go b/internal/pkg/http/httperrors/customerrors/unmarshaling_error.go similarity index 100% rename from internal/pkg/http/http_errors/custom_errors/unmarshaling_error.go rename to internal/pkg/http/httperrors/customerrors/unmarshaling_error.go diff --git a/internal/pkg/http/http_errors/custom_errors/validation_error.go b/internal/pkg/http/httperrors/customerrors/validation_error.go similarity index 100% rename from internal/pkg/http/http_errors/custom_errors/validation_error.go rename to internal/pkg/http/httperrors/customerrors/validation_error.go diff --git a/internal/pkg/http/http_errors/problemDetails/custom_problem_details_errors.go b/internal/pkg/http/httperrors/problemdetails/custom_problem_details_errors.go similarity index 100% rename from internal/pkg/http/http_errors/problemDetails/custom_problem_details_errors.go rename to internal/pkg/http/httperrors/problemdetails/custom_problem_details_errors.go diff --git a/internal/pkg/http/http_errors/problemDetails/option_builder.go b/internal/pkg/http/httperrors/problemdetails/option_builder.go similarity index 100% rename from internal/pkg/http/http_errors/problemDetails/option_builder.go rename to internal/pkg/http/httperrors/problemdetails/option_builder.go diff --git a/internal/pkg/http/http_errors/problemDetails/problem_detail_parser.go b/internal/pkg/http/httperrors/problemdetails/problem_detail_parser.go similarity index 97% rename from internal/pkg/http/http_errors/problemDetails/problem_detail_parser.go rename to internal/pkg/http/httperrors/problemdetails/problem_detail_parser.go index 1f6ce148..f4b86b61 100644 --- a/internal/pkg/http/http_errors/problemDetails/problem_detail_parser.go +++ b/internal/pkg/http/httperrors/problemdetails/problem_detail_parser.go @@ -7,9 +7,9 @@ import ( "reflect" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/constants" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" - errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" + errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/errorutils" "emperror.dev/errors" "github.com/go-playground/validator" diff --git a/internal/pkg/http/http_errors/problemDetails/problem_details.go b/internal/pkg/http/httperrors/problemdetails/problem_details.go similarity index 99% rename from internal/pkg/http/http_errors/problemDetails/problem_details.go rename to internal/pkg/http/httperrors/problemdetails/problem_details.go index b67c499d..f2c7f66b 100644 --- a/internal/pkg/http/http_errors/problemDetails/problem_details.go +++ b/internal/pkg/http/httperrors/problemdetails/problem_details.go @@ -7,7 +7,7 @@ import ( "reflect" "time" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/contracts" defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" diff --git a/internal/pkg/http/http_errors/problemDetails/problem_details_test.go b/internal/pkg/http/httperrors/problemdetails/problem_details_test.go similarity index 98% rename from internal/pkg/http/http_errors/problemDetails/problem_details_test.go rename to internal/pkg/http/httperrors/problemdetails/problem_details_test.go index 0f618e7a..25a05d11 100644 --- a/internal/pkg/http/http_errors/problemDetails/problem_details_test.go +++ b/internal/pkg/http/httperrors/problemdetails/problem_details_test.go @@ -4,7 +4,7 @@ import ( "net/http" "testing" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "emperror.dev/errors" "github.com/stretchr/testify/assert" diff --git a/internal/pkg/mongodb/repository/mongo_generic_repository.go b/internal/pkg/mongodb/repository/mongo_generic_repository.go index 2142dc4d..13f7464d 100644 --- a/internal/pkg/mongodb/repository/mongo_generic_repository.go +++ b/internal/pkg/mongodb/repository/mongo_generic_repository.go @@ -6,7 +6,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/data" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/data/specification" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" reflectionHelper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/reflectionhelper" diff --git a/internal/pkg/mongodb/repository/mongo_generic_repository_test.go b/internal/pkg/mongodb/repository/mongo_generic_repository_test.go index 1ded1163..96b75adf 100644 --- a/internal/pkg/mongodb/repository/mongo_generic_repository_test.go +++ b/internal/pkg/mongodb/repository/mongo_generic_repository_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/data" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" diff --git a/internal/pkg/otel/metrics/metrics.go b/internal/pkg/otel/metrics/metrics.go index a2344bb4..06b9dded 100644 --- a/internal/pkg/otel/metrics/metrics.go +++ b/internal/pkg/otel/metrics/metrics.go @@ -9,7 +9,7 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "emperror.dev/errors" diff --git a/internal/pkg/otel/metrics/metrics_fx.go b/internal/pkg/otel/metrics/metrics_fx.go index 903059ca..0a07fc69 100644 --- a/internal/pkg/otel/metrics/metrics_fx.go +++ b/internal/pkg/otel/metrics/metrics_fx.go @@ -3,7 +3,7 @@ package metrics import ( "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "go.opentelemetry.io/contrib/instrumentation/host" diff --git a/internal/pkg/otel/metrics/metrics_test.go b/internal/pkg/otel/metrics/metrics_test.go index c4b7e21f..89aea69f 100644 --- a/internal/pkg/otel/metrics/metrics_test.go +++ b/internal/pkg/otel/metrics/metrics_test.go @@ -7,7 +7,7 @@ import ( "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" diff --git a/internal/pkg/otel/tracing/utils/utils.go b/internal/pkg/otel/tracing/utils/utils.go index ff03dfb9..4d64caa7 100644 --- a/internal/pkg/otel/tracing/utils/utils.go +++ b/internal/pkg/otel/tracing/utils/utils.go @@ -6,11 +6,10 @@ import ( "reflect" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/grpcErrors" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/problemDetails" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/grpcerrors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants/telemetrytags" - errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" + errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/errorutils" "github.com/ahmetb/go-linq/v3" "go.opentelemetry.io/otel/attribute" @@ -198,7 +197,7 @@ func GrpcTraceErrFromSpan(span trace.Span, err error) error { ) if customErrors.IsCustomError(err) { - grpcErr := grpcErrors.ParseError(err) + grpcErr := grpcerrors.ParseError(err) span.SetAttributes( semconv.RPCGRPCStatusCodeKey.Int(int(grpcErr.GetStatus())), ) diff --git a/internal/pkg/postgresgorm/db.go b/internal/pkg/postgresgorm/db.go index 6e4afe5e..24638ef0 100644 --- a/internal/pkg/postgresgorm/db.go +++ b/internal/pkg/postgresgorm/db.go @@ -19,17 +19,24 @@ func NewGorm(cfg *GormOptions) (*gorm.DB, error) { return nil, errors.New("DBName is required in the config.") } - err := createDB(cfg) - if err != nil { - return nil, err + if cfg.UseSQLLite { + db, err := createSQLLiteDB(cfg.Dns()) + + return db, err } + // InMemory doesn't work correctly with transactions - seems when we `Begin` a transaction on gorm.DB (with SQLLite in-memory) our previous gormDB before transaction will remove and the new gormDB with tx will go on the memory if cfg.UseInMemory { db, err := createInMemoryDB() return db, err } + err := createPostgresDB(cfg) + if err != nil { + return nil, err + } + dataSourceName := fmt.Sprintf( "host=%s port=%d user=%s dbname=%s password=%s", cfg.Host, @@ -70,9 +77,22 @@ func createInMemoryDB() (*gorm.DB, error) { return db, err } +func createSQLLiteDB(dbFilePath string) (*gorm.DB, error) { + // https://gorm.io/docs/connecting_to_the_database.html#SQLite + // https://github.com/glebarez/sqlite + // https://www.connectionstrings.com/sqlite/ + gormSQLLiteDB, err := gorm.Open( + sqlite.Open(dbFilePath), + &gorm.Config{ + Logger: gromlog.NewGormCustomLogger(defaultlogger.GetLogger()), + }) + + return gormSQLLiteDB, err +} + func NewSQLDB(orm *gorm.DB) (*sql.DB, error) { return orm.DB() } -func createDB(cfg *GormOptions) error { +func createPostgresDB(cfg *GormOptions) error { var db *sql.DB // we should choose a default database in the connection, but because we don't have a database yet we specify postgres default database 'postgres' diff --git a/internal/pkg/postgresgorm/gorm_options.go b/internal/pkg/postgresgorm/gorm_options.go index e7e33907..00d8c8be 100644 --- a/internal/pkg/postgresgorm/gorm_options.go +++ b/internal/pkg/postgresgorm/gorm_options.go @@ -2,6 +2,7 @@ package postgresgorm import ( "fmt" + "path/filepath" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" @@ -14,6 +15,7 @@ var optionName = strcase.ToLowerCamel(typeMapper.GetTypeNameByT[GormOptions]()) type GormOptions struct { UseInMemory bool `mapstructure:"useInMemory"` + UseSQLLite bool `mapstructure:"useSqlLite"` Host string `mapstructure:"host"` Port int `mapstructure:"port"` User string `mapstructure:"user"` @@ -24,6 +26,17 @@ type GormOptions struct { } func (h *GormOptions) Dns() string { + if h.UseInMemory { + return "" + } + + if h.UseSQLLite { + projectRootDir := environment.GetProjectRootWorkingDirectory() + dbFilePath := filepath.Join(projectRootDir, fmt.Sprintf("%s.db", h.DBName)) + + return dbFilePath + } + datasource := fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=disable", h.User, h.Password, diff --git a/internal/pkg/postgresgorm/helpers.go b/internal/pkg/postgresgorm/helpers.go deleted file mode 100644 index bd4e0d90..00000000 --- a/internal/pkg/postgresgorm/helpers.go +++ /dev/null @@ -1,70 +0,0 @@ -package postgresgorm - -import ( - "context" - "fmt" - "strings" - - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - - "emperror.dev/errors" - "gorm.io/gorm" -) - -// Ref: https://dev.to/rafaelgfirmino/pagination-using-gorm-scopes-3k5f - -func Paginate[TDataModel any, TEntity any]( - ctx context.Context, - listQuery *utils.ListQuery, - db *gorm.DB, -) (*utils.ListResult[TEntity], error) { - var ( - items []TEntity - totalRows int64 - ) - - dataModel := typeMapper.GenericInstanceByT[TDataModel]() - // https://gorm.io/docs/advanced_query.html - db.WithContext(ctx).Model(dataModel).Count(&totalRows) - - // generate where query - query := db.WithContext(ctx). - Model(dataModel). - Offset(listQuery.GetOffset()). - Limit(listQuery.GetLimit()). - Order(listQuery.GetOrderBy()) - - if listQuery.Filters != nil { - for _, filter := range listQuery.Filters { - column := filter.Field - action := filter.Comparison - value := filter.Value - - switch action { - case "equals": - whereQuery := fmt.Sprintf("%s = ?", column) - query = query.Where(whereQuery, value) - case "contains": - whereQuery := fmt.Sprintf("%s LIKE ?", column) - query = query.Where(whereQuery, "%"+value+"%") - case "in": - whereQuery := fmt.Sprintf("%s IN (?)", column) - queryArray := strings.Split(value, ",") - query = query.Where(whereQuery, queryArray) - } - } - } - - // https://gorm.io/docs/advanced_query.html#Smart-Select-Fields - if err := query.Find(&items).Error; err != nil { - return nil, errors.WrapIf(err, "error in finding products.") - } - - return utils.NewListResult[TEntity]( - items, - listQuery.GetSize(), - listQuery.GetPage(), - totalRows, - ), nil -} diff --git a/internal/pkg/postgresgorm/helpers/helpers.go b/internal/pkg/postgresgorm/helpers/helpers.go index 55afcf00..888877d8 100644 --- a/internal/pkg/postgresgorm/helpers/helpers.go +++ b/internal/pkg/postgresgorm/helpers/helpers.go @@ -5,6 +5,8 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/constants" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/scopes" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "emperror.dev/errors" "gorm.io/gorm" @@ -39,8 +41,34 @@ func GetTxFromContextIfExists(ctx context.Context) *gorm.DB { } func SetTxToContext(ctx context.Context, tx *gorm.DB) *contracts.GormContext { - ctx = context.WithValue(ctx, constants.TxKey, tx) - gormContext := &contracts.GormContext{Tx: tx, Context: ctx} + newCtx := context.WithValue(ctx, constants.TxKey, tx) + gormContext := &contracts.GormContext{Tx: tx, Context: newCtx} + ctx = gormContext return gormContext } + +// Ref: https://dev.to/rafaelgfirmino/pagination-using-gorm-scopes-3k5f + +func Paginate[TDataModel any, TEntity any]( + ctx context.Context, + listQuery *utils.ListQuery, + db *gorm.DB, +) (*utils.ListResult[TEntity], error) { + var ( + items []TEntity + totalRows int64 + ) + + // https://gorm.io/docs/advanced_query.html#Smart-Select-Fields + if err := db.Scopes(scopes.FilterPaginate[TDataModel](ctx, listQuery)).Find(&items).Error; err != nil { + return nil, errors.WrapIf(err, "error in finding products.") + } + + return utils.NewListResult[TEntity]( + items, + listQuery.GetSize(), + listQuery.GetPage(), + totalRows, + ), nil +} diff --git a/internal/pkg/postgresgorm/repository/gorm_generic_repository.go b/internal/pkg/postgresgorm/repository/gorm_generic_repository.go index 39bcf499..2f5c8b77 100644 --- a/internal/pkg/postgresgorm/repository/gorm_generic_repository.go +++ b/internal/pkg/postgresgorm/repository/gorm_generic_repository.go @@ -8,9 +8,9 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/data" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/data/specification" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" reflectionHelper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/reflectionhelper" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" diff --git a/internal/pkg/postgresgorm/repository/gorm_generic_repository_test.go b/internal/pkg/postgresgorm/repository/gorm_generic_repository_test.go index a723aa6e..aa89b6a3 100644 --- a/internal/pkg/postgresgorm/repository/gorm_generic_repository_test.go +++ b/internal/pkg/postgresgorm/repository/gorm_generic_repository_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/data" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" diff --git a/internal/pkg/postgresgorm/scopes/scopes.go b/internal/pkg/postgresgorm/scopes/scopes.go new file mode 100644 index 00000000..0f7620f0 --- /dev/null +++ b/internal/pkg/postgresgorm/scopes/scopes.go @@ -0,0 +1,88 @@ +package scopes + +import ( + "context" + "fmt" + "strings" + + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" + + uuid "github.com/satori/go.uuid" + "gorm.io/gorm" +) + +// https://gorm.io/docs/advanced_query.html#Scopes +// https://gorm.io/docs/scopes.html + +// After scopes, we should have a runner function like Find, Update, Delete + +func AmountGreaterThan1000(db *gorm.DB) *gorm.DB { + return db.Where("amount > ?", 1000) +} + +// FilterAllItemsWithSoftDeleted returns soft-deleted and none soft-deleted items +func FilterAllItemsWithSoftDeleted(db *gorm.DB) *gorm.DB { + // https://gorm.io/docs/delete.html#Find-soft-deleted-records + return db.Unscoped() +} + +// SoftDeleted returns only soft-deleted items +func SoftDeleted(db *gorm.DB) *gorm.DB { + return db.Unscoped().Where("deleted_at IS NOT NULL") +} + +func FilterByTitle(title string) func(db *gorm.DB) *gorm.DB { + return func(db *gorm.DB) *gorm.DB { + return db.Where("title = ?", title) + } +} + +func FilterByID(id uuid.UUID) func(db *gorm.DB) *gorm.DB { + return func(db *gorm.DB) *gorm.DB { + return db.Where("id = ?", id) + } +} + +func FilterPaginate[TDataModel any]( + ctx context.Context, + listQuery *utils.ListQuery, +) func(db *gorm.DB) *gorm.DB { + return func(db *gorm.DB) *gorm.DB { + var totalRows int64 + + dataModel := typeMapper.GenericInstanceByT[TDataModel]() + // https://gorm.io/docs/advanced_query.html + db.WithContext(ctx).Model(dataModel).Count(&totalRows) + + // generate where query + query := db.WithContext(ctx). + Model(dataModel). + Offset(listQuery.GetOffset()). + Limit(listQuery.GetLimit()). + Order(listQuery.GetOrderBy()) + + if listQuery.Filters != nil { + for _, filter := range listQuery.Filters { + column := filter.Field + action := filter.Comparison + value := filter.Value + + switch action { + case "equals": + whereQuery := fmt.Sprintf("%s = ?", column) + query = query.Where(whereQuery, value) + case "contains": + whereQuery := fmt.Sprintf("%s LIKE ?", column) + query = query.Where(whereQuery, "%"+value+"%") + case "in": + whereQuery := fmt.Sprintf("%s IN (?)", column) + queryArray := strings.Split(value, ",") + query = query.Where(whereQuery, queryArray) + } + } + } + + return query + } +} diff --git a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go b/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go index 3e4d0264..16de7c6e 100644 --- a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go +++ b/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go @@ -22,6 +22,18 @@ func NewPostgresMessagePersistenceDBContext( return c } +// WithTx creates a transactional DBContext with getting tx-gorm from the ctx. This will throw an error if the transaction does not exist. +func (c *PostgresMessagePersistenceDBContext) WithTx( + ctx context.Context, +) (*PostgresMessagePersistenceDBContext, error) { + tx, err := helpers.GetTxFromContext(ctx) + if err != nil { + return nil, err + } + + return NewPostgresMessagePersistenceDBContext(tx), nil +} + // WithTxIfExists creates a transactional DBContext with getting tx-gorm from the ctx. not throw an error if the transaction is not existing and returns an existing database. func (c *PostgresMessagePersistenceDBContext) WithTxIfExists( ctx context.Context, diff --git a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository.go b/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service.go similarity index 66% rename from internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository.go rename to internal/pkg/postgresmessaging/messagepersistence/postgres_message_service.go index 3735511a..ff38f9f5 100644 --- a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository.go +++ b/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service.go @@ -2,31 +2,101 @@ package messagepersistence import ( "context" + "errors" "fmt" + "reflect" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/persistmessage" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/contratcs" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" uuid "github.com/satori/go.uuid" ) -type postgresMessagePersistenceRepository struct { +type postgresMessageService struct { messagingDBContext *PostgresMessagePersistenceDBContext + messageSerializer contratcs.MessageSerializer logger logger.Logger } -func NewMessagePersistenceRepository( +func (m *postgresMessageService) Process(messageID string, ctx context.Context) error { + // TODO implement me + panic("implement me") +} + +func (m *postgresMessageService) ProcessAll(ctx context.Context) error { + // TODO implement me + panic("implement me") +} + +func (m *postgresMessageService) AddPublishMessage( + messageEnvelope types.MessageEnvelopeTMessage, + ctx context.Context, +) error { + // TODO implement me + panic("implement me") +} + +func (m *postgresMessageService) AddReceivedMessage(messageEnvelope types.MessageEnvelope, ctx context.Context) error { + // TODO implement me + panic("implement me") +} + +func AddMessageCore( + ctx context.Context, + messageEnvelope types.MessageEnvelope, + deliveryType persistmessage.MessageDeliveryType, +) error { + if messageEnvelope.Message == nil { + return errors.New("messageEnvelope.Message is nil") + } + + var id string + switch message := messageEnvelope.Message.(type) { + case types.IMessage: + id = message.GeMessageId() + // case IInternalCommand: + // id = message.InternalCommandId + default: + id = uuid.NewV4().String() + } + + storeMessage := persistmessage.NewStoreMessage() + + persistmessage.StoreMessage{ + ID: id, + TypeName: reflect.TypeOf(messageEnvelope.Message).Name(), + Serialized: _messageSerializer.Serialize(messageEnvelope), + DeliveryType: deliveryType, + } + + err := _messagePersistenceRepository.AddAsync(storeMessage, cancellationToken) + if err != nil { + return err + } + + _logger.LogInformation( + "Message with id: %v and delivery type: %v saved in persistence message store", + id, + deliveryType, + ) + + return nil +} + +func NewPostgresMessageService( postgresMessagePersistenceDBContext *PostgresMessagePersistenceDBContext, l logger.Logger, -) persistmessage.MessagePersistenceRepository { - return &postgresMessagePersistenceRepository{ +) persistmessage.MessageService { + return &postgresMessageService{ messagingDBContext: postgresMessagePersistenceDBContext, logger: l, } } -func (m *postgresMessagePersistenceRepository) Add( +func (m *postgresMessageService) Add( ctx context.Context, storeMessage *persistmessage.StoreMessage, ) error { @@ -46,7 +116,7 @@ func (m *postgresMessagePersistenceRepository) Add( return nil } -func (m *postgresMessagePersistenceRepository) Update( +func (m *postgresMessageService) Update( ctx context.Context, storeMessage *persistmessage.StoreMessage, ) error { @@ -66,7 +136,7 @@ func (m *postgresMessagePersistenceRepository) Update( return nil } -func (m *postgresMessagePersistenceRepository) ChangeState( +func (m *postgresMessageService) ChangeState( ctx context.Context, messageID uuid.UUID, status persistmessage.MessageStatus, @@ -88,7 +158,7 @@ func (m *postgresMessagePersistenceRepository) ChangeState( return err } -func (m *postgresMessagePersistenceRepository) GetAllActive( +func (m *postgresMessageService) GetAllActive( ctx context.Context, ) ([]*persistmessage.StoreMessage, error) { var storeMessages []*persistmessage.StoreMessage @@ -106,7 +176,7 @@ func (m *postgresMessagePersistenceRepository) GetAllActive( return storeMessages, nil } -func (m *postgresMessagePersistenceRepository) GetByFilter( +func (m *postgresMessageService) GetByFilter( ctx context.Context, predicate func(*persistmessage.StoreMessage) bool, ) ([]*persistmessage.StoreMessage, error) { @@ -122,7 +192,7 @@ func (m *postgresMessagePersistenceRepository) GetByFilter( return storeMessages, nil } -func (m *postgresMessagePersistenceRepository) GetById( +func (m *postgresMessageService) GetById( ctx context.Context, id uuid.UUID, ) (*persistmessage.StoreMessage, error) { @@ -149,7 +219,7 @@ func (m *postgresMessagePersistenceRepository) GetById( return storeMessage, nil } -func (m *postgresMessagePersistenceRepository) Remove( +func (m *postgresMessageService) Remove( ctx context.Context, storeMessage *persistmessage.StoreMessage, ) (bool, error) { @@ -184,7 +254,7 @@ func (m *postgresMessagePersistenceRepository) Remove( return true, nil } -func (m *postgresMessagePersistenceRepository) CleanupMessages( +func (m *postgresMessageService) CleanupMessages( ctx context.Context, ) error { predicate := func(sm *persistmessage.StoreMessage) bool { diff --git a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository_test.go b/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service_test.go similarity index 82% rename from internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository_test.go rename to internal/pkg/postgresmessaging/messagepersistence/postgres_message_service_test.go index 16401686..fd0680ec 100644 --- a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_repository_test.go +++ b/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service_test.go @@ -17,24 +17,24 @@ import ( "gorm.io/gorm" ) -type messagePersistenceRepositoryTest struct { +type postgresMessageServiceTest struct { suite.Suite DB *gorm.DB logger logger.Logger - messagingRepository persistmessage.MessagePersistenceRepository + messagingRepository persistmessage.MessageService dbContext *PostgresMessagePersistenceDBContext storeMessages []*persistmessage.StoreMessage ctx context.Context } -func TestMessagePersistenceRepository(t *testing.T) { +func TestPostgresMessageService(t *testing.T) { suite.Run( t, - &messagePersistenceRepositoryTest{logger: defaultLogger.GetLogger()}, + &postgresMessageServiceTest{logger: defaultLogger.GetLogger()}, ) } -func (c *messagePersistenceRepositoryTest) SetupSuite() { +func (c *postgresMessageServiceTest) SetupSuite() { opts, err := gorm2.NewGormTestContainers(defaultLogger.GetLogger()). PopulateContainerOptions(context.Background(), c.T()) c.Require().NoError(err) @@ -47,13 +47,13 @@ func (c *messagePersistenceRepositoryTest) SetupSuite() { c.Require().NoError(err) c.dbContext = NewPostgresMessagePersistenceDBContext(gormDB) - c.messagingRepository = NewMessagePersistenceRepository( + c.messagingRepository = NewPostgresMessageService( c.dbContext, defaultLogger.GetLogger(), ) } -func (c *messagePersistenceRepositoryTest) SetupTest() { +func (c *postgresMessageServiceTest) SetupTest() { ctx := context.Background() c.ctx = ctx p, err := seedData(context.Background(), c.DB) @@ -61,19 +61,19 @@ func (c *messagePersistenceRepositoryTest) SetupTest() { c.storeMessages = p } -func (c *messagePersistenceRepositoryTest) TearDownTest() { +func (c *postgresMessageServiceTest) TearDownTest() { err := c.cleanupPostgresData() c.Require().NoError(err) } -func (c *messagePersistenceRepositoryTest) BeginTx() { +func (c *postgresMessageServiceTest) BeginTx() { c.logger.Info("starting transaction") tx := c.dbContext.Begin() gormContext := helpers.SetTxToContext(c.ctx, tx) c.ctx = gormContext } -func (c *messagePersistenceRepositoryTest) CommitTx() { +func (c *postgresMessageServiceTest) CommitTx() { tx := helpers.GetTxFromContextIfExists(c.ctx) if tx != nil { c.logger.Info("committing transaction") @@ -81,7 +81,7 @@ func (c *messagePersistenceRepositoryTest) CommitTx() { } } -func (c *messagePersistenceRepositoryTest) Test_Add() { +func (c *postgresMessageServiceTest) Test_Add() { message := &persistmessage.StoreMessage{ ID: uuid.NewV4(), MessageStatus: persistmessage.Processed, @@ -146,7 +146,7 @@ func seedData( return messages, nil } -func (c *messagePersistenceRepositoryTest) cleanupPostgresData() error { +func (c *postgresMessageServiceTest) cleanupPostgresData() error { tables := []string{"store_messages"} // Iterate over the tables and delete all records for _, table := range tables { diff --git a/internal/pkg/postgresmessaging/postgres_messaging_fx.go b/internal/pkg/postgresmessaging/postgres_messaging_fx.go index 16e50948..b62b33fa 100644 --- a/internal/pkg/postgresmessaging/postgres_messaging_fx.go +++ b/internal/pkg/postgresmessaging/postgres_messaging_fx.go @@ -12,7 +12,7 @@ var Module = fx.Module( "postgresmessagingfx", fx.Provide( messagepersistence.NewPostgresMessagePersistenceDBContext, - messagepersistence.NewMessagePersistenceRepository, + messagepersistence.NewPostgresMessageService, ), fx.Invoke(migrateMessaging), ) diff --git a/internal/pkg/rabbitmq/bus/rabbitmq_bus_test.go b/internal/pkg/rabbitmq/bus/rabbitmq_bus_test.go index 5699d3c6..17d83af8 100644 --- a/internal/pkg/rabbitmq/bus/rabbitmq_bus_test.go +++ b/internal/pkg/rabbitmq/bus/rabbitmq_bus_test.go @@ -8,14 +8,16 @@ import ( messageConsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" pipeline2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/pipeline" types3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/json" - defaultLogger2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" + defaultlogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/configurations" consumerConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/factory" + producerfactory "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer" producerConfigurations "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/testcontainer/rabbitmq" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging/consumer" testUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/utils" @@ -26,30 +28,52 @@ import ( func Test_AddRabbitMQ(t *testing.T) { testUtils.SkipCI(t) + ctx := context.Background() fakeConsumer2 := consumer.NewRabbitMQFakeTestConsumerHandler[*ProducerConsumerMessage]() fakeConsumer3 := consumer.NewRabbitMQFakeTestConsumerHandler[*ProducerConsumerMessage]() - serializer := serializer.NewDefaultEventSerializer( - json.NewDefaultSerializer(), + serializer := json.NewDefaultEventJsonSerializer( + json.NewDefaultJsonSerializer(), ) - rabbitmqOptions := &config.RabbitmqOptions{ - RabbitmqHostOptions: &config.RabbitmqHostOptions{ - UserName: "guest", - Password: "guest", - HostName: "localhost", - Port: 5672, - }, + //rabbitmqOptions := &config.RabbitmqOptions{ + // RabbitmqHostOptions: &config.RabbitmqHostOptions{ + // UserName: "guest", + // Password: "guest", + // HostName: "localhost", + // Port: 5672, + // }, + //} + + rabbitmqHostOption, err := rabbitmq.NewRabbitMQTestContainers(defaultlogger.GetLogger()). + PopulateContainerOptions(ctx, t) + require.NoError(t, err) + + options := &config.RabbitmqOptions{ + RabbitmqHostOptions: rabbitmqHostOption, } - conn, err := types.NewRabbitMQConnection(rabbitmqOptions) + + conn, err := types.NewRabbitMQConnection(options) require.NoError(t, err) - b, err := NewRabbitmqBus( - rabbitmqOptions, + consumerFactory := factory.NewConsumerFactory( + options, + conn, serializer, - defaultLogger2.GetLogger(), + defaultlogger.GetLogger(), + ) + producerFactory := producerfactory.NewProducerFactory( + options, conn, + serializer, + defaultlogger.GetLogger(), + ) + + b, err := NewRabbitmqBus( + defaultlogger.GetLogger(), + consumerFactory, + producerFactory, func(builder configurations.RabbitMQConfigurationBuilder) { builder.AddProducer( ProducerConsumerMessage{}, @@ -90,7 +114,6 @@ func Test_AddRabbitMQ(t *testing.T) { err = b.ConnectConsumerHandler(&ProducerConsumerMessage{}, fakeConsumer3) require.NoError(t, err) - ctx := context.Background() err = b.Start(ctx) require.NoError(t, err) @@ -176,7 +199,7 @@ func (p *Pipeline1) Handle( consumerContext.Message().GeMessageId(), ) - err := next() + err := next(ctx) if err != nil { return err } diff --git a/internal/pkg/rabbitmq/consumer/rabbitmq_consumer.go b/internal/pkg/rabbitmq/consumer/rabbitmq_consumer.go index 6ea9a771..fe37142f 100644 --- a/internal/pkg/rabbitmq/consumer/rabbitmq_consumer.go +++ b/internal/pkg/rabbitmq/consumer/rabbitmq_consumer.go @@ -6,19 +6,19 @@ import ( "reflect" "time" - consumer3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" - consumer2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/otel/tracing/consumer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" + consumertracing "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/otel/tracing/consumer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/pipeline" - types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" + messagingTypes "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/contratcs" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/consumer/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/rabbitmqErrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" - errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" + errorutils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/errorutils" "emperror.dev/errors" "github.com/ahmetb/go-linq/v3" @@ -42,16 +42,16 @@ var retryOptions = []retry.Option{ type rabbitMQConsumer struct { rabbitmqConsumerOptions *configurations.RabbitMQConsumerConfiguration connection types.IConnection - handlerDefault consumer3.ConsumerHandler + handlerDefault consumer.ConsumerHandler channel *amqp091.Channel deliveryRoutines chan struct{} // chan should init before using channel - eventSerializer serializer.EventSerializer + messageSerializer contratcs.MessageSerializer logger logger.Logger rabbitmqOptions *config.RabbitmqOptions ErrChan chan error - handlers []consumer3.ConsumerHandler + handlers []consumer.ConsumerHandler pipelines []pipeline.ConsumerPipeline - isConsumedNotifications []func(message types2.IMessage) + isConsumedNotifications []func(message messagingTypes.IMessage) } // NewRabbitMQConsumer create a new generic RabbitMQ consumer @@ -59,10 +59,10 @@ func NewRabbitMQConsumer( rabbitmqOptions *config.RabbitmqOptions, connection types.IConnection, consumerConfiguration *configurations.RabbitMQConsumerConfiguration, - eventSerializer serializer.EventSerializer, + messageSerializer contratcs.MessageSerializer, logger logger.Logger, - isConsumedNotifications ...func(message types2.IMessage), -) (consumer3.Consumer, error) { + isConsumedNotifications ...func(message messagingTypes.IMessage), +) (consumer.Consumer, error) { if consumerConfiguration == nil { return nil, errors.New("consumer configuration is required") } @@ -78,7 +78,7 @@ func NewRabbitMQConsumer( consumerConfiguration.ConcurrencyLimit, ) cons := &rabbitMQConsumer{ - eventSerializer: eventSerializer, + messageSerializer: messageSerializer, rabbitmqOptions: rabbitmqOptions, logger: logger, rabbitmqConsumerOptions: consumerConfiguration, @@ -94,7 +94,7 @@ func NewRabbitMQConsumer( return cons, nil } -func (r *rabbitMQConsumer) IsConsumed(h func(message types2.IMessage)) { +func (r *rabbitMQConsumer) IsConsumed(h func(message messagingTypes.IMessage)) { r.isConsumedNotifications = append(r.isConsumedNotifications, h) } @@ -253,7 +253,7 @@ func (r *rabbitMQConsumer) Stop() error { } } -func (r *rabbitMQConsumer) ConnectHandler(handler consumer3.ConsumerHandler) { +func (r *rabbitMQConsumer) ConnectHandler(handler consumer.ConsumerHandler) { r.handlers = append(r.handlers, handler) } @@ -263,7 +263,7 @@ func (r *rabbitMQConsumer) GetName() string { func (r *rabbitMQConsumer) reConsumeOnDropConnection(ctx context.Context) { go func() { - defer errorUtils.HandlePanic() + defer errorutils.HandlePanic() for { select { case reconnect := <-r.connection.ReconnectedChannel(): @@ -301,7 +301,7 @@ func (r *rabbitMQConsumer) handleReceived( meta = metadata.MapToMetadata(delivery.Headers) } - consumerTraceOption := &consumer2.ConsumerTracingOptions{ + consumerTraceOption := &consumertracing.ConsumerTracingOptions{ MessagingSystem: "rabbitmq", DestinationKind: "queue", Destination: r.rabbitmqConsumerOptions.QueueOptions.Name, @@ -309,7 +309,7 @@ func (r *rabbitMQConsumer) handleReceived( semconv.MessagingRabbitmqDestinationRoutingKey(delivery.RoutingKey), }, } - ctx, beforeConsumeSpan := consumer2.StartConsumerSpan( + ctx, beforeConsumeSpan := consumertracing.StartConsumerSpan( ctx, &meta, string(delivery.Body), @@ -319,7 +319,7 @@ func (r *rabbitMQConsumer) handleReceived( consumeContext, err := r.createConsumeContext(delivery) if err != nil { r.logger.Error( - consumer2.FinishConsumerSpan(beforeConsumeSpan, err), + consumertracing.FinishConsumerSpan(beforeConsumeSpan, err), ) return } @@ -333,11 +333,11 @@ func (r *rabbitMQConsumer) handleReceived( if err := delivery.Ack(false); err != nil { r.logger.Error( "error sending ACK to RabbitMQ consumer: %v", - consumer2.FinishConsumerSpan(beforeConsumeSpan, err), + consumertracing.FinishConsumerSpan(beforeConsumeSpan, err), ) return } - _ = consumer2.FinishConsumerSpan(beforeConsumeSpan, nil) + _ = consumertracing.FinishConsumerSpan(beforeConsumeSpan, nil) if len(r.isConsumedNotifications) > 0 { for _, notification := range r.isConsumedNotifications { if notification != nil { @@ -351,11 +351,11 @@ func (r *rabbitMQConsumer) handleReceived( if err := delivery.Nack(false, true); err != nil { r.logger.Error( "error in sending Nack to RabbitMQ consumer: %v", - consumer2.FinishConsumerSpan(beforeConsumeSpan, err), + consumertracing.FinishConsumerSpan(beforeConsumeSpan, err), ) return } - _ = consumer2.FinishConsumerSpan(beforeConsumeSpan, nil) + _ = consumertracing.FinishConsumerSpan(beforeConsumeSpan, nil) } } @@ -366,7 +366,7 @@ func (r *rabbitMQConsumer) handle( ctx context.Context, ack func(), nack func(), - messageConsumeContext types2.MessageConsumeContext, + messageConsumeContext messagingTypes.MessageConsumeContext, ) { var err error for _, handler := range r.handlers { @@ -390,8 +390,8 @@ func (r *rabbitMQConsumer) handle( func (r *rabbitMQConsumer) runHandlersWithRetry( ctx context.Context, - handler consumer3.ConsumerHandler, - messageConsumeContext types2.MessageConsumeContext, + handler consumer.ConsumerHandler, + messageConsumeContext messagingTypes.MessageConsumeContext, ) error { err := retry.Do(func() error { var lastHandler pipeline.ConsumerHandlerFunc @@ -399,7 +399,7 @@ func (r *rabbitMQConsumer) runHandlersWithRetry( if r.pipelines != nil && len(r.pipelines) > 0 { reversPipes := r.reversOrder(r.pipelines) lastHandler = func(ctx context.Context) error { - handler := handler.(consumer3.ConsumerHandler) + handler := handler.(consumer.ConsumerHandler) return handler.Handle(ctx, messageConsumeContext) } @@ -409,7 +409,7 @@ func (r *rabbitMQConsumer) runHandlersWithRetry( nexValue := next var handlerFunc pipeline.ConsumerHandlerFunc = func(ctx context.Context) error { - genericContext, ok := messageConsumeContext.(types2.MessageConsumeContext) + genericContext, ok := messageConsumeContext.(messagingTypes.MessageConsumeContext) if ok { return pipeValue.Handle( ctx, @@ -419,7 +419,7 @@ func (r *rabbitMQConsumer) runHandlersWithRetry( } return pipeValue.Handle( ctx, - messageConsumeContext.(types2.MessageConsumeContext), + messageConsumeContext.(messagingTypes.MessageConsumeContext), nexValue, ) } @@ -436,7 +436,7 @@ func (r *rabbitMQConsumer) runHandlersWithRetry( } return nil } else { - err := handler.Handle(ctx, messageConsumeContext.(types2.MessageConsumeContext)) + err := handler.Handle(ctx, messageConsumeContext.(messagingTypes.MessageConsumeContext)) if err != nil { return err } @@ -449,34 +449,20 @@ func (r *rabbitMQConsumer) runHandlersWithRetry( func (r *rabbitMQConsumer) createConsumeContext( delivery amqp091.Delivery, -) (types2.MessageConsumeContext, error) { +) (messagingTypes.MessageConsumeContext, error) { message := r.deserializeData( delivery.ContentType, delivery.Type, delivery.Body, ) - if reflect.ValueOf(message).IsZero() || reflect.ValueOf(message).IsNil() { - return *new(types2.MessageConsumeContext), errors.New( - "error in deserialization of payload", - ) - } - m, ok := message.(types2.IMessage) - if !ok || m.IsMessage() == false { - return nil, errors.New( - fmt.Sprintf( - "message %s is not a message type or message property is nil", - utils.GetMessageBaseReflectType(message), - ), - ) - } var meta metadata.Metadata if delivery.Headers != nil { meta = metadata.MapToMetadata(delivery.Headers) } - consumeContext := types2.NewMessageConsumeContext( - message.(types2.IMessage), + consumeContext := messagingTypes.NewMessageConsumeContext( + message, meta, delivery.ContentType, delivery.Type, @@ -492,7 +478,7 @@ func (r *rabbitMQConsumer) deserializeData( contentType string, eventType string, body []byte, -) interface{} { +) messagingTypes.IMessage { if contentType == "" { contentType = "application/json" } @@ -504,8 +490,8 @@ func (r *rabbitMQConsumer) deserializeData( if contentType == "application/json" { // r.rabbitmqConsumerOptions.ConsumerMessageType --> actual type - // deserialize, err := r.eventSerializer.DeserializeType(body, r.rabbitmqConsumerOptions.ConsumerMessageType, contentType) - deserialize, err := r.eventSerializer.DeserializeMessage( + // deserialize, err := r.messageSerializer.DeserializeType(body, r.rabbitmqConsumerOptions.ConsumerMessageType, contentType) + deserialize, err := r.messageSerializer.Deserialize( body, eventType, contentType, diff --git a/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go b/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go index cab253b7..c04b068f 100644 --- a/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go +++ b/internal/pkg/rabbitmq/consumer/rabbitmq_consumer_test.go @@ -9,7 +9,6 @@ import ( messageConsumer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/pipeline" types3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/json" defaultLogger2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/bus" @@ -52,8 +51,8 @@ func Test_Consumer_With_Fake_Message(t *testing.T) { conn, err := types.NewRabbitMQConnection(options) require.NoError(t, err) - eventSerializer := serializer.NewDefaultEventSerializer( - json.NewDefaultSerializer(), + eventSerializer := json.NewDefaultEventJsonSerializer( + json.NewDefaultJsonSerializer(), ) consumerFactory := factory.NewConsumerFactory( options, diff --git a/internal/pkg/rabbitmq/producer/rabbitmq_producer.go b/internal/pkg/rabbitmq/producer/rabbitmq_producer.go index 380c320a..530fb436 100644 --- a/internal/pkg/rabbitmq/producer/rabbitmq_producer.go +++ b/internal/pkg/rabbitmq/producer/rabbitmq_producer.go @@ -2,7 +2,6 @@ package producer import ( "context" - "fmt" "time" messageHeader "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/messageheader" @@ -11,12 +10,11 @@ import ( types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/contratcs" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/producer/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" - typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "emperror.dev/errors" "github.com/rabbitmq/amqp091-go" @@ -29,7 +27,7 @@ type rabbitMQProducer struct { logger logger.Logger rabbitmqOptions *config.RabbitmqOptions connection types.IConnection - eventSerializer serializer.EventSerializer + messageSerializer contratcs.MessageSerializer producersConfigurations map[string]*configurations.RabbitMQProducerConfiguration isProducedNotifications []func(message types2.IMessage) } @@ -39,14 +37,14 @@ func NewRabbitMQProducer( connection types.IConnection, rabbitmqProducersConfiguration map[string]*configurations.RabbitMQProducerConfiguration, logger logger.Logger, - eventSerializer serializer.EventSerializer, + eventSerializer contratcs.MessageSerializer, isProducedNotifications ...func(message types2.IMessage), ) (producer.Producer, error) { p := &rabbitMQProducer{ logger: logger, rabbitmqOptions: cfg, connection: connection, - eventSerializer: eventSerializer, + messageSerializer: eventSerializer, producersConfigurations: rabbitmqProducersConfiguration, } @@ -80,15 +78,6 @@ func (r *rabbitMQProducer) PublishMessageWithTopicName( meta metadata.Metadata, topicOrExchangeName string, ) error { - if message.IsMessage() == false { - return errors.New( - fmt.Sprintf( - "message %s is not a message type or message property is nil", - utils.GetMessageBaseReflectType(message), - ), - ) - } - producerConfiguration := r.getProducerConfigurationByMessage(message) if producerConfiguration == nil { @@ -125,7 +114,7 @@ func (r *rabbitMQProducer) PublishMessageWithTopicName( }, } - serializedObj, err := r.eventSerializer.Serialize(message) + serializedObj, err := r.messageSerializer.Serialize(message) if err != nil { return err } @@ -177,7 +166,7 @@ func (r *rabbitMQProducer) PublishMessageWithTopicName( MessageId: message.GeMessageId(), Timestamp: time.Now(), Headers: metadata.MetadataToMap(meta), - Type: message.GetEventTypeName(), // typeMapper.GetTypeName(message) - just message type name not full type name because in other side package name for type could be different + Type: message.GetMessageTypeName(), // typeMapper.GetTypeName(message) - just message type name not full type name because in other side package name for type could be different ContentType: serializedObj.ContentType, Body: serializedObj.Data, DeliveryMode: producerConfiguration.DeliveryMode, @@ -224,13 +213,9 @@ func (r *rabbitMQProducer) getMetadata( ) metadata.Metadata { meta = metadata.FromMetadata(meta) - if message.GetEventTypeName() == "" { - message.SetEventTypeName( - typeMapper.GetTypeName(message), - ) // just message type name not full type name because in other side package name for type could be different) - } - messageHeader.SetMessageType(meta, message.GetEventTypeName()) - messageHeader.SetMessageContentType(meta, r.eventSerializer.ContentType()) + // just message type name not full type name because in other side package name for type could be different + messageHeader.SetMessageType(meta, message.GetMessageTypeName()) + messageHeader.SetMessageContentType(meta, r.messageSerializer.ContentType()) if messageHeader.GetMessageId(meta) == "" { messageHeader.SetMessageId(meta, message.GeMessageId()) diff --git a/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go b/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go index 8920bd34..ea3b367f 100644 --- a/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go +++ b/internal/pkg/rabbitmq/producer/rabbitmq_producer_test.go @@ -6,12 +6,12 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" types2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/json" defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/testcontainer/rabbitmq" testUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/utils" uuid "github.com/satori/go.uuid" @@ -21,8 +21,8 @@ import ( func Test_Publish_Message(t *testing.T) { testUtils.SkipCI(t) - eventSerializer := serializer.NewDefaultEventSerializer( - json.NewDefaultSerializer(), + eventSerializer := json.NewDefaultEventJsonSerializer( + json.NewDefaultJsonSerializer(), ) ctx := context.Background() @@ -42,23 +42,21 @@ func Test_Publish_Message(t *testing.T) { } defer tp.Shutdown(ctx) - //conn, err := types.NewRabbitMQConnection(&config.RabbitmqOptions{ + //options := &config.RabbitmqOptions{ // RabbitmqHostOptions: &config.RabbitmqHostOptions{ // UserName: "guest", // Password: "guest", // HostName: "localhost", // Port: 5672, // }, - //}) - //require.NoError(t, err) + //} + + rabbitmqHostOption, err := rabbitmq.NewRabbitMQTestContainers(defaultLogger.GetLogger()). + PopulateContainerOptions(ctx, t) + require.NoError(t, err) options := &config.RabbitmqOptions{ - RabbitmqHostOptions: &config.RabbitmqHostOptions{ - UserName: "guest", - Password: "guest", - HostName: "localhost", - Port: 5672, - }, + RabbitmqHostOptions: rabbitmqHostOption, } conn, err := types.NewRabbitMQConnection(options) diff --git a/internal/pkg/rabbitmq/rabbitmq_fx.go b/internal/pkg/rabbitmq/rabbitmq_fx.go index 81ffc4ff..ae594718 100644 --- a/internal/pkg/rabbitmq/rabbitmq_fx.go +++ b/internal/pkg/rabbitmq/rabbitmq_fx.go @@ -33,9 +33,8 @@ var ( // - order is not important in provide // - provide can have parameter and will resolve if registered // - execute its func only if it requested - rabbitmqProviders = fx.Options(fx.Provide( //nolint:gochecknoglobals - config.ProvideConfig, - ), + rabbitmqProviders = fx.Options( + fx.Provide(config.ProvideConfig), fx.Provide(types.NewRabbitMQConnection), fx.Provide(fx.Annotate( bus.NewRabbitmqBus, diff --git a/internal/pkg/rabbitmq/types/connection.go b/internal/pkg/rabbitmq/types/connection.go index f7e3a645..0c0194ac 100644 --- a/internal/pkg/rabbitmq/types/connection.go +++ b/internal/pkg/rabbitmq/types/connection.go @@ -5,7 +5,7 @@ import ( defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" - errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" + errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/errorutils" "emperror.dev/errors" "github.com/rabbitmq/amqp091-go" diff --git a/internal/pkg/reflection/typemapper/type_mapper.go b/internal/pkg/reflection/typemapper/type_mapper.go index 3e9ee222..e380a262 100644 --- a/internal/pkg/reflection/typemapper/type_mapper.go +++ b/internal/pkg/reflection/typemapper/type_mapper.go @@ -120,6 +120,7 @@ func TypeByNameAndImplementedInterface[TInterface interface{}]( } } } + return nil } @@ -322,7 +323,7 @@ func InstanceByTypeName(name string) interface{} { return getInstanceFromType(typ) } -func InstanceByTypeNameAndImplementedInterface[TInterface interface{}]( +func EmptyInstanceByTypeNameAndImplementedInterface[TInterface interface{}]( name string, ) interface{} { typ := TypeByNameAndImplementedInterface[TInterface](name) @@ -330,6 +331,15 @@ func InstanceByTypeNameAndImplementedInterface[TInterface interface{}]( return getInstanceFromType(typ) } +func EmptyInstanceByTypeAndImplementedInterface[TInterface interface{}]( + typ reflect.Type, +) interface{} { + // we use short type name instead of full type name because this typ in other receiver packages could have different package name + typeName := GetTypeName(typ) + + return EmptyInstanceByTypeNameAndImplementedInterface[TInterface](typeName) +} + // InstancePointerByTypeName return an empty pointer instance of the type by its name // If the type is a pointer type, it will return a pointer instance of the type and // if the type is a struct type, it will return a pointer to the struct diff --git a/internal/pkg/reflection/typemapper/type_mapper_test.go b/internal/pkg/reflection/typemapper/type_mapper_test.go index d204ddeb..6a9d515a 100644 --- a/internal/pkg/reflection/typemapper/type_mapper_test.go +++ b/internal/pkg/reflection/typemapper/type_mapper_test.go @@ -14,7 +14,7 @@ func TestTypes(t *testing.T) { q22 := InstanceByTypeName("*typeMapper.Test").(*Test) q222 := InstancePointerByTypeName("*typeMapper.Test").(*Test) q3 := TypeByNameAndImplementedInterface[ITest]("*typeMapper.Test") - q4 := InstanceByTypeNameAndImplementedInterface[ITest]("*typeMapper.Test") + q4 := EmptyInstanceByTypeNameAndImplementedInterface[ITest]("*typeMapper.Test") c1 := GetTypeFromGeneric[Test]() c2 := GetTypeFromGeneric[*Test]() diff --git a/internal/pkg/utils/error_utils/errors.go b/internal/pkg/utils/errorutils/errors.go similarity index 98% rename from internal/pkg/utils/error_utils/errors.go rename to internal/pkg/utils/errorutils/errors.go index 308ef2e0..0ee26503 100644 --- a/internal/pkg/utils/error_utils/errors.go +++ b/internal/pkg/utils/errorutils/errors.go @@ -5,7 +5,7 @@ import ( "runtime/debug" "strings" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/contracts" defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "emperror.dev/errors" diff --git a/internal/pkg/utils/error_utils/errors_test.go b/internal/pkg/utils/errorutils/errors_test.go similarity index 100% rename from internal/pkg/utils/error_utils/errors_test.go rename to internal/pkg/utils/errorutils/errors_test.go diff --git a/internal/services/catalog_read_service/.env b/internal/services/catalog_read_service/.env deleted file mode 100644 index c307987a..00000000 --- a/internal/services/catalog_read_service/.env +++ /dev/null @@ -1 +0,0 @@ -PROJECT_NAME=catalog_read_service diff --git a/internal/services/catalog_write_service/.env b/internal/services/catalog_write_service/.env deleted file mode 100644 index aa77c30f..00000000 --- a/internal/services/catalog_write_service/.env +++ /dev/null @@ -1 +0,0 @@ -PROJECT_NAME=catalog_write_service diff --git a/internal/services/catalog_read_service/.air.toml b/internal/services/catalogreadservice/.air.toml similarity index 100% rename from internal/services/catalog_read_service/.air.toml rename to internal/services/catalogreadservice/.air.toml diff --git a/internal/services/catalog_read_service/.dockerignore b/internal/services/catalogreadservice/.dockerignore similarity index 100% rename from internal/services/catalog_read_service/.dockerignore rename to internal/services/catalogreadservice/.dockerignore diff --git a/internal/services/catalogreadservice/.env b/internal/services/catalogreadservice/.env new file mode 100644 index 00000000..e19f4d52 --- /dev/null +++ b/internal/services/catalogreadservice/.env @@ -0,0 +1 @@ +PROJECT_NAME=catalogreadservice diff --git a/internal/services/catalog_read_service/.gitignore b/internal/services/catalogreadservice/.gitignore similarity index 100% rename from internal/services/catalog_read_service/.gitignore rename to internal/services/catalogreadservice/.gitignore diff --git a/internal/services/catalog_read_service/.golangci.yml b/internal/services/catalogreadservice/.golangci.yml similarity index 100% rename from internal/services/catalog_read_service/.golangci.yml rename to internal/services/catalogreadservice/.golangci.yml diff --git a/internal/services/catalog_read_service/Dockerfile b/internal/services/catalogreadservice/Dockerfile similarity index 100% rename from internal/services/catalog_read_service/Dockerfile rename to internal/services/catalogreadservice/Dockerfile diff --git a/internal/services/catalog_read_service/Makefile b/internal/services/catalogreadservice/Makefile similarity index 100% rename from internal/services/catalog_read_service/Makefile rename to internal/services/catalogreadservice/Makefile diff --git a/internal/services/catalog_read_service/arch-go.yml b/internal/services/catalogreadservice/arch-go.yml similarity index 100% rename from internal/services/catalog_read_service/arch-go.yml rename to internal/services/catalogreadservice/arch-go.yml diff --git a/internal/services/catalog_read_service/client.http b/internal/services/catalogreadservice/client.http similarity index 100% rename from internal/services/catalog_read_service/client.http rename to internal/services/catalogreadservice/client.http diff --git a/internal/services/catalog_read_service/cmd/app/main.go b/internal/services/catalogreadservice/cmd/app/main.go similarity index 100% rename from internal/services/catalog_read_service/cmd/app/main.go rename to internal/services/catalogreadservice/cmd/app/main.go diff --git a/internal/services/catalog_read_service/cmd/migration/.gitkeep b/internal/services/catalogreadservice/cmd/migration/.gitkeep similarity index 100% rename from internal/services/catalog_read_service/cmd/migration/.gitkeep rename to internal/services/catalogreadservice/cmd/migration/.gitkeep diff --git a/internal/services/catalog_read_service/config/config.development.json b/internal/services/catalogreadservice/config/config.development.json similarity index 95% rename from internal/services/catalog_read_service/config/config.development.json rename to internal/services/catalogreadservice/config/config.development.json index b8f8f6fc..6b988ae3 100644 --- a/internal/services/catalog_read_service/config/config.development.json +++ b/internal/services/catalogreadservice/config/config.development.json @@ -1,16 +1,16 @@ { "appOptions": { - "serviceName": "catalogs_read_service", + "serviceName": "catalogreadservice", "deliveryType": "http" }, "grpcOptions": { - "name": "catalogs_read_service", + "name": "catalogreadservice", "port": ":6004", "host": "localhost", "development": true }, "echoHttpOptions": { - "name": "catalogs_read_service", + "name": "catalogreadservice", "port": ":7001", "development": true, "timeout": 30, diff --git a/internal/services/catalog_read_service/config/config.go b/internal/services/catalogreadservice/config/config.go similarity index 100% rename from internal/services/catalog_read_service/config/config.go rename to internal/services/catalogreadservice/config/config.go diff --git a/internal/services/catalog_read_service/config/config.test.json b/internal/services/catalogreadservice/config/config.test.json similarity index 95% rename from internal/services/catalog_read_service/config/config.test.json rename to internal/services/catalogreadservice/config/config.test.json index 0fa84110..5038d505 100644 --- a/internal/services/catalog_read_service/config/config.test.json +++ b/internal/services/catalogreadservice/config/config.test.json @@ -1,16 +1,16 @@ { "appOptions": { - "serviceName": "catalogs_read_service", + "serviceName": "catalogreadservice", "deliveryType": "http" }, "grpcOptions": { - "name": "catalogs_read_service", + "name": "catalogsreadservice", "port": ":3300", "host": "localhost", "development": true }, "echoHttpOptions": { - "name": "catalogs_read_service", + "name": "catalogreadservice", "port": ":6000", "development": true, "timeout": 30, diff --git a/internal/services/catalog_read_service/config/confix_fx.go b/internal/services/catalogreadservice/config/confix_fx.go similarity index 100% rename from internal/services/catalog_read_service/config/confix_fx.go rename to internal/services/catalogreadservice/config/confix_fx.go diff --git a/internal/services/catalog_read_service/docs/docs.go b/internal/services/catalogreadservice/docs/docs.go similarity index 100% rename from internal/services/catalog_read_service/docs/docs.go rename to internal/services/catalogreadservice/docs/docs.go diff --git a/internal/services/catalog_read_service/docs/swagger.json b/internal/services/catalogreadservice/docs/swagger.json similarity index 100% rename from internal/services/catalog_read_service/docs/swagger.json rename to internal/services/catalogreadservice/docs/swagger.json diff --git a/internal/services/catalog_read_service/docs/swagger.yaml b/internal/services/catalogreadservice/docs/swagger.yaml similarity index 100% rename from internal/services/catalog_read_service/docs/swagger.yaml rename to internal/services/catalogreadservice/docs/swagger.yaml diff --git a/internal/services/catalog_read_service/go.mod b/internal/services/catalogreadservice/go.mod similarity index 95% rename from internal/services/catalog_read_service/go.mod rename to internal/services/catalogreadservice/go.mod index 989903f6..31438437 100644 --- a/internal/services/catalog_read_service/go.mod +++ b/internal/services/catalogreadservice/go.mod @@ -7,7 +7,7 @@ replace github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg => ../../ require ( emperror.dev/errors v0.8.1 - github.com/brianvoe/gofakeit/v6 v6.23.2 + github.com/brianvoe/gofakeit/v6 v6.25.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 @@ -28,6 +28,7 @@ require ( go.opentelemetry.io/otel/metric v1.19.0 go.opentelemetry.io/otel/trace v1.19.0 go.uber.org/fx v1.20.0 + gorm.io/gorm v1.25.5 ) require ( @@ -36,7 +37,6 @@ require ( atomicgo.dev/schedule v0.1.0 // indirect dario.cat/mergo v1.0.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/EventStore/EventStore-Client-Go v1.0.2 // indirect github.com/KyleBanks/depth v1.2.1 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect @@ -61,10 +61,13 @@ require ( github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/doug-martin/goqu/v9 v9.18.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/fatih/color v1.15.0 // indirect github.com/fatih/structs v1.0.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect + github.com/glebarez/go-sqlite v1.21.2 // indirect + github.com/glebarez/sqlite v1.10.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect @@ -76,11 +79,9 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/goccy/go-reflect v1.2.0 // indirect - github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang-migrate/migrate/v4 v4.16.2 // indirect - github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/go-querystring v1.1.0 // indirect @@ -147,6 +148,7 @@ require ( github.com/rabbitmq/amqp091-go v1.8.1 // indirect github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/samber/lo v1.38.1 // indirect github.com/sergi/go-diff v1.2.0 // indirect @@ -166,13 +168,14 @@ require ( github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect + github.com/ulule/limiter/v3 v3.11.2 // indirect github.com/uptrace/bun v1.1.16 // indirect github.com/uptrace/bun/driver/pgdriver v1.1.16 // indirect github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.3 // indirect github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3 // indirect github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.27.0 // indirect + github.com/valyala/fasthttp v1.47.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect github.com/vmihailenco/msgpack/v5 v5.4.0 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect @@ -224,8 +227,11 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gorm.io/driver/postgres v1.5.2 // indirect - gorm.io/gorm v1.25.4 // indirect gorm.io/plugin/opentelemetry v0.1.4 // indirect mellium.im/sasl v0.3.1 // indirect + modernc.org/libc v1.24.1 // indirect + modernc.org/mathutil v1.6.0 // indirect + modernc.org/memory v1.6.0 // indirect + modernc.org/sqlite v1.25.0 // indirect moul.io/http2curl v1.0.1-0.20190925090545-5cd742060b0e // indirect ) diff --git a/internal/services/catalog_read_service/go.sum b/internal/services/catalogreadservice/go.sum similarity index 92% rename from internal/services/catalog_read_service/go.sum rename to internal/services/catalogreadservice/go.sum index 024e0f77..58dd0c77 100644 --- a/internal/services/catalog_read_service/go.sum +++ b/internal/services/catalogreadservice/go.sum @@ -6,7 +6,6 @@ atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8= atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ= atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs= atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU= -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -56,15 +55,12 @@ emperror.dev/errors v0.8.1 h1:UavXZ5cSX/4u9iyvH6aDcuGkVjeexUGJ7Ij7G4VfQT0= emperror.dev/errors v0.8.1/go.mod h1:YcRvLPh626Ubn2xqtoprejnA5nFha+TJ+2vew48kWuE= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/EventStore/EventStore-Client-Go v1.0.2 h1:onM2TIInLhWUJwUQ/5a/8blNrrbhwrtm7Tpmg13ohiw= -github.com/EventStore/EventStore-Client-Go v1.0.2/go.mod h1:NOqSOtNxqGizr1Qnf7joGGLK6OkeoLV/QEI893A43H0= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= @@ -80,13 +76,10 @@ github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030I github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.1 h1:hJ3s7GbWlGK4YVV92sO88BQSyF4ZLVy7/awqOlPxFbA= github.com/Microsoft/hcsshim v0.11.1/go.mod h1:nFJmaO4Zr5Y7eADdFOpYswDDlNVbvcIJJNJLECr5JQg= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2/go.mod h1:VSw57q4QFiWDbRnjdX8Cb3Ow0SFncRw+bA/ofY6Q83w= github.com/ahmetb/go-linq/v3 v3.2.0 h1:BEuMfp+b59io8g5wYzNoFe9pWPalRklhlhbiU3hYZDE= @@ -106,8 +99,8 @@ github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/brianvoe/gofakeit/v6 v6.23.2 h1:lVde18uhad5wII/f5RMVFLtdQNE0HaGFuBUXmYKk8i8= -github.com/brianvoe/gofakeit/v6 v6.23.2/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8= +github.com/brianvoe/gofakeit/v6 v6.25.0 h1:ZpFjktOpLZUeF8q223o0rUuXtA+m5qW5srjvVi+JkXk= +github.com/brianvoe/gofakeit/v6 v6.25.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= @@ -116,17 +109,14 @@ github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/caarlos0/env/v8 v8.0.0 h1:POhxHhSpuxrLMIdvTGARuZqR4Jjm8AYmoi/JKlcScs0= github.com/caarlos0/env/v8 v8.0.0/go.mod h1:7K4wMY9bH0esiXSSHlfHLX5xKGQMnkH5Fk4TDSSSzfo= -github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -135,47 +125,37 @@ github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+g github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/containerd v1.7.6 h1:oNAVsnhPoy4BTPQivLgTzI9Oleml9l/+eYIDYXRCYo8= github.com/containerd/containerd v1.7.6/go.mod h1:SY6lrkkuJT40BVNO37tlYTSnKJnP5AXBc0fhx0q+TJ4= -github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= -github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= -github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.1/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY= -github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE= github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/doug-martin/goqu/v9 v9.18.0 h1:/6bcuEtAe6nsSMVK/M+fOiXUNfyFF3yYtE07DBPFMYY= github.com/doug-martin/goqu/v9 v9.18.0/go.mod h1:nf0Wc2/hV3gYK9LiyqIrzBEVGlI8qW3GuDCEobC4wBQ= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -190,7 +170,6 @@ github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/structs v1.0.0 h1:BrX964Rv5uQ3wwS+KRUAJCBBw5PQmgJfJ6v4yly5QwU= github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -201,6 +180,10 @@ github.com/gavv/httpexpect/v2 v2.3.1 h1:sGLlKMn8AuHS9ztK9Sb7AJ7OxIL8v2PcLdyxfKt1 github.com/gavv/httpexpect/v2 v2.3.1/go.mod h1:yOE8m/aqFYQDNrgprMeXgq4YynfN9h1NgcE1+1suV64= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= +github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= +github.com/glebarez/sqlite v1.10.0 h1:u4gt8y7OND/cCei/NMHmfbLxF6xP2wgKcT/BJf2pYkc= +github.com/glebarez/sqlite v1.10.0/go.mod h1:IJ+lfSOmiekhQsFTJRx/lHtGYmCdtAiTaf5wI9u5uHA= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -246,8 +229,6 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-reflect v1.2.0 h1:O0T8rZCuNmGXewnATuKYnkL0xm6o8UNOJZd/gOkb9ms= github.com/goccy/go-reflect v1.2.0/go.mod h1:n0oYZn8VcV2CkWTxi8B9QjkCoq6GTtCEdfmR66YhFtE= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= @@ -271,8 +252,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -328,8 +307,6 @@ github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ= github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= @@ -341,8 +318,6 @@ github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQ github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= -github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e h1:XmA6L9IPRdUr28a+SK/oMchGgQy159wvzXA5tJ7l+40= -github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e/go.mod h1:AFIo+02s+12CEg8Gzz9kzhCbmbq6JcKNrhHffCGA9z4= github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= @@ -366,11 +341,8 @@ github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSAS github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/imkira/go-interpol v1.0.0 h1:HrmLyvOLJyjR0YofMw8QGdCIuYOs4TJUBDNU5sJC09E= github.com/imkira/go-interpol v1.0.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= @@ -473,11 +445,9 @@ github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhR github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= -github.com/lib/pq v0.0.0-20180327071824-d34b9ff171c2/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= @@ -518,10 +488,6 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mcuadros/go-defaults v1.2.0 h1:FODb8WSf0uGaY8elWJAkoLL0Ri6AlZ1bFlenk56oZtc= github.com/mcuadros/go-defaults v1.2.0/go.mod h1:WEZtHEVIGYVDqkKSWBdWKUVdRyKlMfulPaGDWIVeCWY= -github.com/mehdihadeli/go-mediatr v1.1.10 h1:NAzg4065c90lgYeb+Vzbd2WKH0tUFpxzL0mpx6hkU/A= -github.com/mehdihadeli/go-mediatr v1.1.10/go.mod h1:lwgZl7qVL/RKomObBblhG3uEte/r4nJDV95Vd+nGrMw= -github.com/mehdihadeli/go-mediatr v1.2.0 h1:XkzYF/uGfW4pwPWYAxKyY+mO6l989PbmCQWSYHuCZtU= -github.com/mehdihadeli/go-mediatr v1.2.0/go.mod h1:I9LuExxAKz6cTDJyP/SSDSmkHaPHK1/usnvEXjUY47k= github.com/mehdihadeli/go-mediatr v1.3.0 h1:hrb5Scp/nsiR3Y62mjZ0Tc5UX/dRJl4nDFkINBEIESA= github.com/mehdihadeli/go-mediatr v1.3.0/go.mod h1:lsG+hyH+pEOhmZiZl0KPO72BcZiEReF03CBk4GVJB0k= github.com/michaelklishin/rabbit-hole v1.5.0 h1:Bex27BiFDsijCM9D0ezSHqyy0kehpYHuNKaPqq/a4RM= @@ -530,10 +496,8 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= -github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= -github.com/moby/term v0.0.0-20200915141129-7f0af18e79f2/go.mod h1:TjQg8pa4iejrUrjiz0MCtMV38jdMNW4doKSiBrEvCQQ= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= @@ -541,7 +505,6 @@ github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8 github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nolleh/caption_json_formatter v0.2.2 h1:EKsOr/fCllNQF2ZoajfbSDlV73BNV1bDu1aTTSRrlN0= github.com/nolleh/caption_json_formatter v0.2.2/go.mod h1:5FYofZA8NAej/eFxa12FvyQKosU1LfyKizZPlY0JojU= @@ -560,27 +523,17 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.28.0 h1:i2rg/p9n/UqIDAMFUJ6qIUUMcsqOuUHgbpbu235Vr1c= github.com/onsi/gomega v1.28.0/go.mod h1:A1H2JE76sI14WIP57LMKj7FVfCHx3g3BcZVjJG8bjX8= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc95/go.mod h1:z+bZxa/+Tz/FmYVWkhUajJdzFeOqjc5vrqskhVyHGUM= github.com/opencontainers/runc v1.1.9 h1:XR0VIHTGce5eWPkaPesqTBrhW2yAcaraWfsEalNwQLM= github.com/opencontainers/runc v1.1.9/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.4.2 h1:zjqfqHjUpPmB3c1GlCvvgsM1G4LkvqQbBDueDOCg/jA= github.com/openzipkin/zipkin-go v0.4.2/go.mod h1:ZeVkFjuuBiSy13y8vpSDCjMi9GoI3hPpCJSBx/EYFhY= -github.com/ory/dockertest/v3 v3.6.3/go.mod h1:EFLcVUOl8qCwp9NyDAcCDtq/QviLtYswW/VbWzUnTNE= -github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4= -github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= -github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -617,6 +570,8 @@ github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnA github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -626,7 +581,6 @@ github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncj github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= @@ -634,7 +588,6 @@ github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/savsgio/gotils v0.0.0-20210617111740-97865ed5a873 h1:N3Af8f13ooDKcIhsmFT7Z05CStZWu4C7Md0uDEy4q6o= github.com/savsgio/gotils v0.0.0-20210617111740-97865ed5a873/go.mod h1:dmPawKuiAeG/aFYVs2i+Dyosoo7FNcm+Pi8iK6ZUrX8= -github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= @@ -648,11 +601,8 @@ github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9Nz github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY= @@ -663,13 +613,10 @@ github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= -github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= @@ -703,7 +650,6 @@ github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM= github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04= github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/testcontainers/testcontainers-go v0.25.0 h1:erH6cQjsaJrH+rJDU9qIf89KFdhK0Bft0aEZHlYC3Vs= github.com/testcontainers/testcontainers-go v0.25.0/go.mod h1:4sC9SiJyzD1XFi59q8umTQYWxnkweEc5OjVtTUlJzqQ= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= @@ -713,6 +659,8 @@ github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+F github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= +github.com/ulule/limiter/v3 v3.11.2 h1:P4yOrxoEMJbOTfRJR2OzjL90oflzYPPmWg+dvwN2tHA= +github.com/ulule/limiter/v3 v3.11.2/go.mod h1:QG5GnFOCV+k7lrL5Y8kgEeeflPH3+Cviqlqa8SVSQxI= github.com/uptrace/bun v1.1.16 h1:cn9cgEMFwcyYRsQLfxCRMUxyK1WaHwOVrR3TvzEFZ/A= github.com/uptrace/bun v1.1.16/go.mod h1:7HnsMRRvpLFUcquJxp22JO8PsWKpFQO/gNXqqsuGWg8= github.com/uptrace/bun/driver/pgdriver v1.1.16 h1:b/NiSXk6Ldw7KLfMLbOqIkm4odHd7QiNOCPLqPFJjK4= @@ -723,22 +671,19 @@ github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3 h1:LyGS9cIZV0YVhE81zwf github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3/go.mod h1:RvCYhPchLhvQ9l9C9goblbgO7BaKt597kBMf5mgKyo0= github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3 h1:2na5W81H38Z4qXCQCuzlcdSMiTWgPJ6XeZIArq6VIJE= github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3/go.mod h1:9IVEh9mPv3NwFf99dVLX15FqVgdpZJ8RMDo/Cr0vK74= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.27.0 h1:gDefRDL9aqSiwXV6aRW8aSBPs82y4KizSzHrBLf4NDI= github.com/valyala/fasthttp v1.27.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA= +github.com/valyala/fasthttp v1.47.0 h1:y7moDoxYzMooFpT5aHgNgVOQDrS3qlkfiP9mDtGGK9c= +github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vmihailenco/msgpack/v5 v5.4.0 h1:hRM0digJwyR6vll33NNAwCFguy5JuBD6jxDmQP3l608= github.com/vmihailenco/msgpack/v5 v5.4.0/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= @@ -773,7 +718,6 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= @@ -850,7 +794,6 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= @@ -907,7 +850,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= @@ -926,7 +868,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -947,7 +888,6 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -975,7 +915,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= @@ -992,7 +931,6 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1001,7 +939,6 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1019,9 +956,7 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1034,8 +969,6 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1097,7 +1030,6 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1142,7 +1074,6 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= @@ -1209,7 +1140,6 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1254,10 +1184,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1266,7 +1194,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= @@ -1277,7 +1204,6 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -1291,11 +1217,10 @@ gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0= gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8= gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c= gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I= -gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= -gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= +gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/plugin/opentelemetry v0.1.4 h1:7p0ocWELjSSRI7NCKPW2mVe6h43YPini99sNJcbsTuc= gorm.io/plugin/opentelemetry v0.1.4/go.mod h1:tndJHOdvPT0pyGhOb8E2209eXJCUxhC5UpKw7bGVWeI= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1307,6 +1232,14 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= mellium.im/sasl v0.3.1 h1:wE0LW6g7U83vhvxjC1IY8DnXM+EU095yeo8XClvCdfo= mellium.im/sasl v0.3.1/go.mod h1:xm59PUYpZHhgQ9ZqoJ5QaCqzWMi8IeS49dhp6plPCzw= +modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM= +modernc.org/libc v1.24.1/go.mod h1:FmfO1RLrU3MHJfyi9eYYmZBfi/R+tqZ6+hQ3yQQUkak= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.6.0 h1:i6mzavxrE9a30whzMfwf7XWVODx2r5OYXvU46cirX7o= +modernc.org/memory v1.6.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/sqlite v1.25.0 h1:AFweiwPNd/b3BoKnBOfFm+Y260guGMF+0UFk0savqeA= +modernc.org/sqlite v1.25.0/go.mod h1:FL3pVXie73rg3Rii6V/u5BoHlSoyeZeIgKZEgHARyCU= moul.io/http2curl v1.0.1-0.20190925090545-5cd742060b0e h1:C7q+e9M5nggAvWfVg9Nl66kebKeuJlP3FD58V4RR5wo= moul.io/http2curl v1.0.1-0.20190925090545-5cd742060b0e/go.mod h1:nejbQVfXh96n9dSF6cH3Jsk/QI1Z2oEL7sSI2ifXFNA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/internal/services/catalog_read_service/internal/products/configurations/mappings/mapping_profile.go b/internal/services/catalogreadservice/internal/products/configurations/mappings/mapping_profile.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/configurations/mappings/mapping_profile.go rename to internal/services/catalogreadservice/internal/products/configurations/mappings/mapping_profile.go diff --git a/internal/services/catalog_read_service/internal/products/configurations/mediator/mediator_configurations.go b/internal/services/catalogreadservice/internal/products/configurations/mediator/mediator_configurations.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/configurations/mediator/mediator_configurations.go rename to internal/services/catalogreadservice/internal/products/configurations/mediator/mediator_configurations.go diff --git a/internal/services/catalog_read_service/internal/products/configurations/products_module_configurator.go b/internal/services/catalogreadservice/internal/products/configurations/products_module_configurator.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/configurations/products_module_configurator.go rename to internal/services/catalogreadservice/internal/products/configurations/products_module_configurator.go diff --git a/internal/services/catalog_read_service/internal/products/configurations/rabbitmq/rabbitmq_configuration.go b/internal/services/catalogreadservice/internal/products/configurations/rabbitmq/rabbitmq_configuration.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/configurations/rabbitmq/rabbitmq_configuration.go rename to internal/services/catalogreadservice/internal/products/configurations/rabbitmq/rabbitmq_configuration.go diff --git a/internal/services/catalog_read_service/internal/products/consts/consts.go b/internal/services/catalogreadservice/internal/products/consts/consts.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/consts/consts.go rename to internal/services/catalogreadservice/internal/products/consts/consts.go diff --git a/internal/services/catalog_read_service/internal/products/contracts/data/product_cache_repository.go b/internal/services/catalogreadservice/internal/products/contracts/data/product_cache_repository.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/contracts/data/product_cache_repository.go rename to internal/services/catalogreadservice/internal/products/contracts/data/product_cache_repository.go diff --git a/internal/services/catalog_read_service/internal/products/contracts/data/product_repository.go b/internal/services/catalogreadservice/internal/products/contracts/data/product_repository.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/contracts/data/product_repository.go rename to internal/services/catalogreadservice/internal/products/contracts/data/product_repository.go diff --git a/internal/services/catalog_read_service/internal/products/contracts/params/product_route_params.go b/internal/services/catalogreadservice/internal/products/contracts/params/product_route_params.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/contracts/params/product_route_params.go rename to internal/services/catalogreadservice/internal/products/contracts/params/product_route_params.go diff --git a/internal/services/catalog_read_service/internal/products/data/repositories/mongo_product_repository.go b/internal/services/catalogreadservice/internal/products/data/repositories/mongo_product_repository.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/data/repositories/mongo_product_repository.go rename to internal/services/catalogreadservice/internal/products/data/repositories/mongo_product_repository.go diff --git a/internal/services/catalog_read_service/internal/products/data/repositories/redis_product_repository.go b/internal/services/catalogreadservice/internal/products/data/repositories/redis_product_repository.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/data/repositories/redis_product_repository.go rename to internal/services/catalogreadservice/internal/products/data/repositories/redis_product_repository.go diff --git a/internal/services/catalog_read_service/internal/products/dto/product_dto.go b/internal/services/catalogreadservice/internal/products/dto/product_dto.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/dto/product_dto.go rename to internal/services/catalogreadservice/internal/products/dto/product_dto.go diff --git a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/create_product.go b/internal/services/catalogreadservice/internal/products/features/creating_product/v1/create_product.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/creating_product/v1/create_product.go rename to internal/services/catalogreadservice/internal/products/features/creating_product/v1/create_product.go diff --git a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/create_product_handler.go b/internal/services/catalogreadservice/internal/products/features/creating_product/v1/create_product_handler.go similarity index 98% rename from internal/services/catalog_read_service/internal/products/features/creating_product/v1/create_product_handler.go rename to internal/services/catalogreadservice/internal/products/features/creating_product/v1/create_product_handler.go index b8eb7309..fa59ec4b 100644 --- a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/create_product_handler.go +++ b/internal/services/catalogreadservice/internal/products/features/creating_product/v1/create_product_handler.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" diff --git a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/dtos/create_product_response_dto.go b/internal/services/catalogreadservice/internal/products/features/creating_product/v1/dtos/create_product_response_dto.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/creating_product/v1/dtos/create_product_response_dto.go rename to internal/services/catalogreadservice/internal/products/features/creating_product/v1/dtos/create_product_response_dto.go diff --git a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created.go b/internal/services/catalogreadservice/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created.go rename to internal/services/catalogreadservice/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created.go diff --git a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created_consumer.go b/internal/services/catalogreadservice/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created_consumer.go similarity index 97% rename from internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created_consumer.go rename to internal/services/catalogreadservice/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created_consumer.go index c47b9738..479f39b0 100644 --- a/internal/services/catalog_read_service/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created_consumer.go +++ b/internal/services/catalogreadservice/internal/products/features/creating_product/v1/events/integrationevents/externalevents/product_created_consumer.go @@ -6,7 +6,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/creating_product/v1" diff --git a/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/commands/delete_product.go b/internal/services/catalogreadservice/internal/products/features/deleting_products/v1/commands/delete_product.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/deleting_products/v1/commands/delete_product.go rename to internal/services/catalogreadservice/internal/products/features/deleting_products/v1/commands/delete_product.go diff --git a/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/commands/delete_product_handler.go b/internal/services/catalogreadservice/internal/products/features/deleting_products/v1/commands/delete_product_handler.go similarity index 97% rename from internal/services/catalog_read_service/internal/products/features/deleting_products/v1/commands/delete_product_handler.go rename to internal/services/catalogreadservice/internal/products/features/deleting_products/v1/commands/delete_product_handler.go index 68a8711b..bfe4f51e 100644 --- a/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/commands/delete_product_handler.go +++ b/internal/services/catalogreadservice/internal/products/features/deleting_products/v1/commands/delete_product_handler.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" diff --git a/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted.go b/internal/services/catalogreadservice/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted.go rename to internal/services/catalogreadservice/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted.go diff --git a/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted_consumer.go b/internal/services/catalogreadservice/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted_consumer.go similarity index 97% rename from internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted_consumer.go rename to internal/services/catalogreadservice/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted_consumer.go index 7b91c075..378b1188 100644 --- a/internal/services/catalog_read_service/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted_consumer.go +++ b/internal/services/catalogreadservice/internal/products/features/deleting_products/v1/events/integration_events/external_events/product_deleted_consumer.go @@ -5,7 +5,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/deleting_products/v1/commands" diff --git a/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/dtos/get_product_by_id_request_dto.go b/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/dtos/get_product_by_id_request_dto.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/dtos/get_product_by_id_request_dto.go rename to internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/dtos/get_product_by_id_request_dto.go diff --git a/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/dtos/get_product_by_id_response_dto.go b/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/dtos/get_product_by_id_response_dto.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/dtos/get_product_by_id_response_dto.go rename to internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/dtos/get_product_by_id_response_dto.go diff --git a/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/endpoints/get_product_by_id_endpoint.go b/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/endpoints/get_product_by_id_endpoint.go similarity index 97% rename from internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/endpoints/get_product_by_id_endpoint.go rename to internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/endpoints/get_product_by_id_endpoint.go index da5a4c16..63659962 100644 --- a/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/endpoints/get_product_by_id_endpoint.go +++ b/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/endpoints/get_product_by_id_endpoint.go @@ -4,7 +4,7 @@ import ( "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/params" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/queries" diff --git a/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/queries/get_product_by_id.go b/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/queries/get_product_by_id.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/queries/get_product_by_id.go rename to internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/queries/get_product_by_id.go diff --git a/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/queries/get_product_by_id_handler.go b/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/queries/get_product_by_id_handler.go similarity index 98% rename from internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/queries/get_product_by_id_handler.go rename to internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/queries/get_product_by_id_handler.go index 58b4b2ff..fabf678c 100644 --- a/internal/services/catalog_read_service/internal/products/features/get_product_by_id/v1/queries/get_product_by_id_handler.go +++ b/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/queries/get_product_by_id_handler.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" diff --git a/internal/services/catalog_read_service/internal/products/features/getting_products/v1/dtos/get_products_request_dto.go b/internal/services/catalogreadservice/internal/products/features/getting_products/v1/dtos/get_products_request_dto.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/getting_products/v1/dtos/get_products_request_dto.go rename to internal/services/catalogreadservice/internal/products/features/getting_products/v1/dtos/get_products_request_dto.go diff --git a/internal/services/catalog_read_service/internal/products/features/getting_products/v1/dtos/get_products_response_dto.go b/internal/services/catalogreadservice/internal/products/features/getting_products/v1/dtos/get_products_response_dto.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/getting_products/v1/dtos/get_products_response_dto.go rename to internal/services/catalogreadservice/internal/products/features/getting_products/v1/dtos/get_products_response_dto.go diff --git a/internal/services/catalog_read_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go b/internal/services/catalogreadservice/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go similarity index 98% rename from internal/services/catalog_read_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go rename to internal/services/catalogreadservice/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go index 1ecf134c..2369558b 100644 --- a/internal/services/catalog_read_service/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go +++ b/internal/services/catalogreadservice/internal/products/features/getting_products/v1/endpoints/get_products_endpoint.go @@ -4,7 +4,7 @@ import ( "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/params" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/getting_products/v1/dtos" diff --git a/internal/services/catalog_read_service/internal/products/features/getting_products/v1/queries/get_products.go b/internal/services/catalogreadservice/internal/products/features/getting_products/v1/queries/get_products.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/getting_products/v1/queries/get_products.go rename to internal/services/catalogreadservice/internal/products/features/getting_products/v1/queries/get_products.go diff --git a/internal/services/catalog_read_service/internal/products/features/getting_products/v1/queries/get_products_handler.go b/internal/services/catalogreadservice/internal/products/features/getting_products/v1/queries/get_products_handler.go similarity index 97% rename from internal/services/catalog_read_service/internal/products/features/getting_products/v1/queries/get_products_handler.go rename to internal/services/catalogreadservice/internal/products/features/getting_products/v1/queries/get_products_handler.go index 1cba0c1c..3fd0a93c 100644 --- a/internal/services/catalog_read_service/internal/products/features/getting_products/v1/queries/get_products_handler.go +++ b/internal/services/catalogreadservice/internal/products/features/getting_products/v1/queries/get_products_handler.go @@ -3,7 +3,7 @@ package queries import ( "context" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" diff --git a/internal/services/catalog_read_service/internal/products/features/searching_products/v1/dtos/search_products_request_dto.go b/internal/services/catalogreadservice/internal/products/features/searching_products/v1/dtos/search_products_request_dto.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/searching_products/v1/dtos/search_products_request_dto.go rename to internal/services/catalogreadservice/internal/products/features/searching_products/v1/dtos/search_products_request_dto.go diff --git a/internal/services/catalog_read_service/internal/products/features/searching_products/v1/dtos/search_products_response_dto.go b/internal/services/catalogreadservice/internal/products/features/searching_products/v1/dtos/search_products_response_dto.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/searching_products/v1/dtos/search_products_response_dto.go rename to internal/services/catalogreadservice/internal/products/features/searching_products/v1/dtos/search_products_response_dto.go diff --git a/internal/services/catalog_read_service/internal/products/features/searching_products/v1/endpoints/search_products_endpoint.go b/internal/services/catalogreadservice/internal/products/features/searching_products/v1/endpoints/search_products_endpoint.go similarity index 98% rename from internal/services/catalog_read_service/internal/products/features/searching_products/v1/endpoints/search_products_endpoint.go rename to internal/services/catalogreadservice/internal/products/features/searching_products/v1/endpoints/search_products_endpoint.go index e33447c3..2455d0d1 100644 --- a/internal/services/catalog_read_service/internal/products/features/searching_products/v1/endpoints/search_products_endpoint.go +++ b/internal/services/catalogreadservice/internal/products/features/searching_products/v1/endpoints/search_products_endpoint.go @@ -4,7 +4,7 @@ import ( "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/params" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/searching_products/v1/dtos" diff --git a/internal/services/catalog_read_service/internal/products/features/searching_products/v1/queries/search_products.go b/internal/services/catalogreadservice/internal/products/features/searching_products/v1/queries/search_products.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/searching_products/v1/queries/search_products.go rename to internal/services/catalogreadservice/internal/products/features/searching_products/v1/queries/search_products.go diff --git a/internal/services/catalog_read_service/internal/products/features/searching_products/v1/queries/search_products_handler.go b/internal/services/catalogreadservice/internal/products/features/searching_products/v1/queries/search_products_handler.go similarity index 97% rename from internal/services/catalog_read_service/internal/products/features/searching_products/v1/queries/search_products_handler.go rename to internal/services/catalogreadservice/internal/products/features/searching_products/v1/queries/search_products_handler.go index c5ba5375..81c95ccb 100644 --- a/internal/services/catalog_read_service/internal/products/features/searching_products/v1/queries/search_products_handler.go +++ b/internal/services/catalogreadservice/internal/products/features/searching_products/v1/queries/search_products_handler.go @@ -3,7 +3,7 @@ package queries import ( "context" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" diff --git a/internal/services/catalog_read_service/internal/products/features/updating_products/v1/commands/update_product.go b/internal/services/catalogreadservice/internal/products/features/updating_products/v1/commands/update_product.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/updating_products/v1/commands/update_product.go rename to internal/services/catalogreadservice/internal/products/features/updating_products/v1/commands/update_product.go diff --git a/internal/services/catalog_read_service/internal/products/features/updating_products/v1/commands/update_product_handler.go b/internal/services/catalogreadservice/internal/products/features/updating_products/v1/commands/update_product_handler.go similarity index 98% rename from internal/services/catalog_read_service/internal/products/features/updating_products/v1/commands/update_product_handler.go rename to internal/services/catalogreadservice/internal/products/features/updating_products/v1/commands/update_product_handler.go index 4ccb786e..702d9155 100644 --- a/internal/services/catalog_read_service/internal/products/features/updating_products/v1/commands/update_product_handler.go +++ b/internal/services/catalogreadservice/internal/products/features/updating_products/v1/commands/update_product_handler.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/contracts/data" diff --git a/internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated.go b/internal/services/catalogreadservice/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated.go rename to internal/services/catalogreadservice/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated.go diff --git a/internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated_consumer.go b/internal/services/catalogreadservice/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated_consumer.go similarity index 98% rename from internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated_consumer.go rename to internal/services/catalogreadservice/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated_consumer.go index 1defa8a6..1df5b42e 100644 --- a/internal/services/catalog_read_service/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated_consumer.go +++ b/internal/services/catalogreadservice/internal/products/features/updating_products/v1/events/integration_events/external_events/product_updated_consumer.go @@ -6,7 +6,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/consumer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" diff --git a/internal/services/catalog_read_service/internal/products/models/product.go b/internal/services/catalogreadservice/internal/products/models/product.go similarity index 100% rename from internal/services/catalog_read_service/internal/products/models/product.go rename to internal/services/catalogreadservice/internal/products/models/product.go diff --git a/internal/services/catalog_read_service/internal/products/products_fx.go b/internal/services/catalogreadservice/internal/products/products_fx.go similarity index 98% rename from internal/services/catalog_read_service/internal/products/products_fx.go rename to internal/services/catalogreadservice/internal/products/products_fx.go index 5fe53c96..732157e6 100644 --- a/internal/services/catalog_read_service/internal/products/products_fx.go +++ b/internal/services/catalogreadservice/internal/products/products_fx.go @@ -2,7 +2,7 @@ package products import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/data/repositories" getProductByIdV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/get_product_by_id/v1/endpoints" getProductsV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/features/getting_products/v1/endpoints" diff --git a/internal/services/catalog_read_service/internal/shared/app/app.go b/internal/services/catalogreadservice/internal/shared/app/app.go similarity index 100% rename from internal/services/catalog_read_service/internal/shared/app/app.go rename to internal/services/catalogreadservice/internal/shared/app/app.go diff --git a/internal/services/catalog_read_service/internal/shared/app/application.go b/internal/services/catalogreadservice/internal/shared/app/application.go similarity index 100% rename from internal/services/catalog_read_service/internal/shared/app/application.go rename to internal/services/catalogreadservice/internal/shared/app/application.go diff --git a/internal/services/catalog_read_service/internal/shared/app/application_builder.go b/internal/services/catalogreadservice/internal/shared/app/application_builder.go similarity index 100% rename from internal/services/catalog_read_service/internal/shared/app/application_builder.go rename to internal/services/catalogreadservice/internal/shared/app/application_builder.go diff --git a/internal/services/catalog_read_service/internal/shared/app/test/test_app.go b/internal/services/catalogreadservice/internal/shared/app/test/test_app.go similarity index 99% rename from internal/services/catalog_read_service/internal/shared/app/test/test_app.go rename to internal/services/catalogreadservice/internal/shared/app/test/test_app.go index ca8518c1..6430781c 100644 --- a/internal/services/catalog_read_service/internal/shared/app/test/test_app.go +++ b/internal/services/catalogreadservice/internal/shared/app/test/test_app.go @@ -7,7 +7,7 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" - config3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/config" + config3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/bus" diff --git a/internal/services/catalog_read_service/internal/shared/app/test/test_application.go b/internal/services/catalogreadservice/internal/shared/app/test/test_application.go similarity index 100% rename from internal/services/catalog_read_service/internal/shared/app/test/test_application.go rename to internal/services/catalogreadservice/internal/shared/app/test/test_application.go diff --git a/internal/services/catalog_read_service/internal/shared/app/test/test_application_builder.go b/internal/services/catalogreadservice/internal/shared/app/test/test_application_builder.go similarity index 100% rename from internal/services/catalog_read_service/internal/shared/app/test/test_application_builder.go rename to internal/services/catalogreadservice/internal/shared/app/test/test_application_builder.go diff --git a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/catalogs_configurator.go b/internal/services/catalogreadservice/internal/shared/configurations/catalogs/catalogs_configurator.go similarity index 98% rename from internal/services/catalog_read_service/internal/shared/configurations/catalogs/catalogs_configurator.go rename to internal/services/catalogreadservice/internal/shared/configurations/catalogs/catalogs_configurator.go index ccd5b53e..18682207 100644 --- a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/catalogs_configurator.go +++ b/internal/services/catalogreadservice/internal/shared/configurations/catalogs/catalogs_configurator.go @@ -5,7 +5,7 @@ import ( "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/configurations/catalogs/infrastructure" diff --git a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go b/internal/services/catalogreadservice/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go similarity index 94% rename from internal/services/catalog_read_service/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go rename to internal/services/catalogreadservice/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go index 1389e6e4..180f501a 100644 --- a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go +++ b/internal/services/catalogreadservice/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go @@ -1,7 +1,7 @@ package catalogs import ( - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/docs" "github.com/labstack/echo/v4" diff --git a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/catalogs_fx.go b/internal/services/catalogreadservice/internal/shared/configurations/catalogs/catalogs_fx.go similarity index 100% rename from internal/services/catalog_read_service/internal/shared/configurations/catalogs/catalogs_fx.go rename to internal/services/catalogreadservice/internal/shared/configurations/catalogs/catalogs_fx.go diff --git a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go b/internal/services/catalogreadservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go similarity index 100% rename from internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go rename to internal/services/catalogreadservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go diff --git a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go b/internal/services/catalogreadservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go similarity index 98% rename from internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go rename to internal/services/catalogreadservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go index 9e39923e..ab9682d3 100644 --- a/internal/services/catalog_read_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go +++ b/internal/services/catalogreadservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go @@ -4,7 +4,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health" - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" diff --git a/internal/services/catalog_read_service/internal/shared/contracts/catalogs_metrics.go b/internal/services/catalogreadservice/internal/shared/contracts/catalogs_metrics.go similarity index 100% rename from internal/services/catalog_read_service/internal/shared/contracts/catalogs_metrics.go rename to internal/services/catalogreadservice/internal/shared/contracts/catalogs_metrics.go diff --git a/internal/services/catalog_read_service/internal/shared/testfixture/integration/integration_test_fixture.go b/internal/services/catalogreadservice/internal/shared/testfixture/integration/integration_test_fixture.go similarity index 100% rename from internal/services/catalog_read_service/internal/shared/testfixture/integration/integration_test_fixture.go rename to internal/services/catalogreadservice/internal/shared/testfixture/integration/integration_test_fixture.go diff --git a/internal/services/catalog_read_service/mocks/ProductCacheRepository.go b/internal/services/catalogreadservice/mocks/ProductCacheRepository.go similarity index 100% rename from internal/services/catalog_read_service/mocks/ProductCacheRepository.go rename to internal/services/catalogreadservice/mocks/ProductCacheRepository.go diff --git a/internal/services/catalog_read_service/mocks/ProductRepository.go b/internal/services/catalogreadservice/mocks/ProductRepository.go similarity index 100% rename from internal/services/catalog_read_service/mocks/ProductRepository.go rename to internal/services/catalogreadservice/mocks/ProductRepository.go diff --git a/internal/services/catalog_read_service/mocks/UnsafeProductsServiceServer.go b/internal/services/catalogreadservice/mocks/UnsafeProductsServiceServer.go similarity index 100% rename from internal/services/catalog_read_service/mocks/UnsafeProductsServiceServer.go rename to internal/services/catalogreadservice/mocks/UnsafeProductsServiceServer.go diff --git a/internal/services/catalog_read_service/readme.md b/internal/services/catalogreadservice/readme.md similarity index 100% rename from internal/services/catalog_read_service/readme.md rename to internal/services/catalogreadservice/readme.md diff --git a/internal/services/catalog_read_service/revive-config.toml b/internal/services/catalogreadservice/revive-config.toml similarity index 100% rename from internal/services/catalog_read_service/revive-config.toml rename to internal/services/catalogreadservice/revive-config.toml diff --git a/internal/services/catalog_read_service/staticcheck.conf b/internal/services/catalogreadservice/staticcheck.conf similarity index 100% rename from internal/services/catalog_read_service/staticcheck.conf rename to internal/services/catalogreadservice/staticcheck.conf diff --git a/internal/services/catalog_read_service/taskfile.yml b/internal/services/catalogreadservice/taskfile.yml similarity index 100% rename from internal/services/catalog_read_service/taskfile.yml rename to internal/services/catalogreadservice/taskfile.yml diff --git a/internal/services/catalog_read_service/taskfile_db.yml b/internal/services/catalogreadservice/taskfile_db.yml similarity index 100% rename from internal/services/catalog_read_service/taskfile_db.yml rename to internal/services/catalogreadservice/taskfile_db.yml diff --git a/internal/services/catalog_read_service/taskfile_test.yml b/internal/services/catalogreadservice/taskfile_test.yml similarity index 100% rename from internal/services/catalog_read_service/taskfile_test.yml rename to internal/services/catalogreadservice/taskfile_test.yml diff --git a/internal/services/catalog_read_service/test/end_to_end/products/features/getting_product_by_id/v1/get_product_by_id_test.go b/internal/services/catalogreadservice/test/end_to_end/products/features/getting_product_by_id/v1/get_product_by_id_test.go similarity index 100% rename from internal/services/catalog_read_service/test/end_to_end/products/features/getting_product_by_id/v1/get_product_by_id_test.go rename to internal/services/catalogreadservice/test/end_to_end/products/features/getting_product_by_id/v1/get_product_by_id_test.go diff --git a/internal/services/catalog_read_service/test/end_to_end/products/features/getting_products/v1/get_products_endpoint_test.go b/internal/services/catalogreadservice/test/end_to_end/products/features/getting_products/v1/get_products_endpoint_test.go similarity index 100% rename from internal/services/catalog_read_service/test/end_to_end/products/features/getting_products/v1/get_products_endpoint_test.go rename to internal/services/catalogreadservice/test/end_to_end/products/features/getting_products/v1/get_products_endpoint_test.go diff --git a/internal/services/catalog_read_service/test/integration/products/data/mongo_product_repository_test.go b/internal/services/catalogreadservice/test/integration/products/data/mongo_product_repository_test.go similarity index 99% rename from internal/services/catalog_read_service/test/integration/products/data/mongo_product_repository_test.go rename to internal/services/catalogreadservice/test/integration/products/data/mongo_product_repository_test.go index 4ec46057..e9dab242 100644 --- a/internal/services/catalog_read_service/test/integration/products/data/mongo_product_repository_test.go +++ b/internal/services/catalogreadservice/test/integration/products/data/mongo_product_repository_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/products/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogreadservice/internal/shared/testfixture/integration" diff --git a/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/commands/create_product_test.go b/internal/services/catalogreadservice/test/integration/products/features/creating_product/v1/commands/create_product_test.go similarity index 100% rename from internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/commands/create_product_test.go rename to internal/services/catalogreadservice/test/integration/products/features/creating_product/v1/commands/create_product_test.go diff --git a/internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/events/product_created_test.go b/internal/services/catalogreadservice/test/integration/products/features/creating_product/v1/events/product_created_test.go similarity index 100% rename from internal/services/catalog_read_service/test/integration/products/features/creating_product/v1/events/product_created_test.go rename to internal/services/catalogreadservice/test/integration/products/features/creating_product/v1/events/product_created_test.go diff --git a/internal/services/catalog_read_service/test/integration/products/features/deleting_product/v1/commands/delete_product_test.go b/internal/services/catalogreadservice/test/integration/products/features/deleting_product/v1/commands/delete_product_test.go similarity index 100% rename from internal/services/catalog_read_service/test/integration/products/features/deleting_product/v1/commands/delete_product_test.go rename to internal/services/catalogreadservice/test/integration/products/features/deleting_product/v1/commands/delete_product_test.go diff --git a/internal/services/catalog_read_service/test/integration/products/features/deleting_product/v1/events/product_deleted_test.go b/internal/services/catalogreadservice/test/integration/products/features/deleting_product/v1/events/product_deleted_test.go similarity index 100% rename from internal/services/catalog_read_service/test/integration/products/features/deleting_product/v1/events/product_deleted_test.go rename to internal/services/catalogreadservice/test/integration/products/features/deleting_product/v1/events/product_deleted_test.go diff --git a/internal/services/catalog_read_service/test/integration/products/features/getting_product_by_id/v1/queries/get_product_by_id_test.go b/internal/services/catalogreadservice/test/integration/products/features/getting_product_by_id/v1/queries/get_product_by_id_test.go similarity index 100% rename from internal/services/catalog_read_service/test/integration/products/features/getting_product_by_id/v1/queries/get_product_by_id_test.go rename to internal/services/catalogreadservice/test/integration/products/features/getting_product_by_id/v1/queries/get_product_by_id_test.go diff --git a/internal/services/catalog_read_service/test/integration/products/features/getting_products/v1/queries/get_products_handler_test.go b/internal/services/catalogreadservice/test/integration/products/features/getting_products/v1/queries/get_products_handler_test.go similarity index 100% rename from internal/services/catalog_read_service/test/integration/products/features/getting_products/v1/queries/get_products_handler_test.go rename to internal/services/catalogreadservice/test/integration/products/features/getting_products/v1/queries/get_products_handler_test.go diff --git a/internal/services/catalog_read_service/test/integration/products/features/updating_product/v1/commands/update_product_handler_test.go b/internal/services/catalogreadservice/test/integration/products/features/updating_product/v1/commands/update_product_handler_test.go similarity index 100% rename from internal/services/catalog_read_service/test/integration/products/features/updating_product/v1/commands/update_product_handler_test.go rename to internal/services/catalogreadservice/test/integration/products/features/updating_product/v1/commands/update_product_handler_test.go diff --git a/internal/services/catalog_read_service/test/integration/products/features/updating_product/v1/events/product_updated_test.go b/internal/services/catalogreadservice/test/integration/products/features/updating_product/v1/events/product_updated_test.go similarity index 100% rename from internal/services/catalog_read_service/test/integration/products/features/updating_product/v1/events/product_updated_test.go rename to internal/services/catalogreadservice/test/integration/products/features/updating_product/v1/events/product_updated_test.go diff --git a/internal/services/catalog_read_service/test/load_tests/.openapi-generator-ignore b/internal/services/catalogreadservice/test/load_tests/.openapi-generator-ignore similarity index 100% rename from internal/services/catalog_read_service/test/load_tests/.openapi-generator-ignore rename to internal/services/catalogreadservice/test/load_tests/.openapi-generator-ignore diff --git a/internal/services/catalog_read_service/test/load_tests/.openapi-generator/FILES b/internal/services/catalogreadservice/test/load_tests/.openapi-generator/FILES similarity index 100% rename from internal/services/catalog_read_service/test/load_tests/.openapi-generator/FILES rename to internal/services/catalogreadservice/test/load_tests/.openapi-generator/FILES diff --git a/internal/services/catalog_read_service/test/load_tests/.openapi-generator/VERSION b/internal/services/catalogreadservice/test/load_tests/.openapi-generator/VERSION similarity index 100% rename from internal/services/catalog_read_service/test/load_tests/.openapi-generator/VERSION rename to internal/services/catalogreadservice/test/load_tests/.openapi-generator/VERSION diff --git a/internal/services/catalog_read_service/test/load_tests/README.md b/internal/services/catalogreadservice/test/load_tests/README.md similarity index 100% rename from internal/services/catalog_read_service/test/load_tests/README.md rename to internal/services/catalogreadservice/test/load_tests/README.md diff --git a/internal/services/catalog_read_service/test/load_tests/script.js b/internal/services/catalogreadservice/test/load_tests/script.js similarity index 100% rename from internal/services/catalog_read_service/test/load_tests/script.js rename to internal/services/catalogreadservice/test/load_tests/script.js diff --git a/internal/services/catalog_write_service/.air.toml b/internal/services/catalogwriteservice/.air.toml similarity index 100% rename from internal/services/catalog_write_service/.air.toml rename to internal/services/catalogwriteservice/.air.toml diff --git a/internal/services/catalog_write_service/.dockerignore b/internal/services/catalogwriteservice/.dockerignore similarity index 100% rename from internal/services/catalog_write_service/.dockerignore rename to internal/services/catalogwriteservice/.dockerignore diff --git a/internal/services/catalogwriteservice/.env b/internal/services/catalogwriteservice/.env new file mode 100644 index 00000000..2e06f00a --- /dev/null +++ b/internal/services/catalogwriteservice/.env @@ -0,0 +1 @@ +PROJECT_NAME=catalogwriteservice diff --git a/internal/services/catalog_write_service/.gitignore b/internal/services/catalogwriteservice/.gitignore similarity index 100% rename from internal/services/catalog_write_service/.gitignore rename to internal/services/catalogwriteservice/.gitignore diff --git a/internal/services/catalog_write_service/.golangci.yml b/internal/services/catalogwriteservice/.golangci.yml similarity index 100% rename from internal/services/catalog_write_service/.golangci.yml rename to internal/services/catalogwriteservice/.golangci.yml diff --git a/internal/services/catalog_write_service/Dockerfile b/internal/services/catalogwriteservice/Dockerfile similarity index 100% rename from internal/services/catalog_write_service/Dockerfile rename to internal/services/catalogwriteservice/Dockerfile diff --git a/internal/services/catalog_write_service/Makefile b/internal/services/catalogwriteservice/Makefile similarity index 100% rename from internal/services/catalog_write_service/Makefile rename to internal/services/catalogwriteservice/Makefile diff --git a/internal/services/catalog_write_service/arch-go.yml b/internal/services/catalogwriteservice/arch-go.yml similarity index 100% rename from internal/services/catalog_write_service/arch-go.yml rename to internal/services/catalogwriteservice/arch-go.yml diff --git a/internal/services/catalog_write_service/atlas.hcl b/internal/services/catalogwriteservice/atlas.hcl similarity index 100% rename from internal/services/catalog_write_service/atlas.hcl rename to internal/services/catalogwriteservice/atlas.hcl diff --git a/internal/services/catalog_write_service/client.http b/internal/services/catalogwriteservice/client.http similarity index 100% rename from internal/services/catalog_write_service/client.http rename to internal/services/catalogwriteservice/client.http diff --git a/internal/services/catalog_write_service/cmd/app/main.go b/internal/services/catalogwriteservice/cmd/app/main.go similarity index 100% rename from internal/services/catalog_write_service/cmd/app/main.go rename to internal/services/catalogwriteservice/cmd/app/main.go diff --git a/internal/services/catalog_write_service/cmd/migration/main.go b/internal/services/catalogwriteservice/cmd/migration/main.go similarity index 100% rename from internal/services/catalog_write_service/cmd/migration/main.go rename to internal/services/catalogwriteservice/cmd/migration/main.go diff --git a/internal/services/catalog_write_service/config/app_options.go b/internal/services/catalogwriteservice/config/app_options.go similarity index 100% rename from internal/services/catalog_write_service/config/app_options.go rename to internal/services/catalogwriteservice/config/app_options.go diff --git a/internal/services/catalog_write_service/config/config.development.json b/internal/services/catalogwriteservice/config/config.development.json similarity index 95% rename from internal/services/catalog_write_service/config/config.development.json rename to internal/services/catalogwriteservice/config/config.development.json index f3719637..bcdc2233 100644 --- a/internal/services/catalog_write_service/config/config.development.json +++ b/internal/services/catalogwriteservice/config/config.development.json @@ -1,16 +1,16 @@ { "appOptions": { - "serviceName": "catalogs_write_service", + "serviceName": "catalogwriteservice", "deliveryType": "http" }, "grpcOptions": { - "name": "catalogs_write_service", + "name": "catalogwriteservice", "port": ":6003", "host": "localhost", "development": true }, "echoHttpOptions": { - "name": "catalogs_write_service", + "name": "catalogwriteservice", "port": ":7000", "development": true, "timeout": 30, diff --git a/internal/services/catalog_write_service/config/config.test.json b/internal/services/catalogwriteservice/config/config.test.json similarity index 94% rename from internal/services/catalog_write_service/config/config.test.json rename to internal/services/catalogwriteservice/config/config.test.json index a3bbbe20..8de7c47b 100644 --- a/internal/services/catalog_write_service/config/config.test.json +++ b/internal/services/catalogwriteservice/config/config.test.json @@ -1,16 +1,16 @@ { "appOptions": { - "serviceName": "catalogs_write_service", + "serviceName": "catalogwriteservice", "deliveryType": "http" }, "grpcOptions": { - "name": "catalogs_write_service", + "name": "catalogwriteservice", "port": ":3301", "host": "localhost", "development": true }, "echoHttpOptions": { - "name": "catalogs_write_service", + "name": "catalogwriteservice", "port": ":6001", "development": true, "timeout": 30, diff --git a/internal/services/catalog_write_service/config/config_fx.go b/internal/services/catalogwriteservice/config/config_fx.go similarity index 100% rename from internal/services/catalog_write_service/config/config_fx.go rename to internal/services/catalogwriteservice/config/config_fx.go diff --git a/internal/services/catalog_write_service/db/fixtures/products/products.yaml b/internal/services/catalogwriteservice/db/fixtures/products/products.yaml similarity index 100% rename from internal/services/catalog_write_service/db/fixtures/products/products.yaml rename to internal/services/catalogwriteservice/db/fixtures/products/products.yaml diff --git a/internal/services/catalog_write_service/db/migrations/atlas/20230919170700.sql b/internal/services/catalogwriteservice/db/migrations/atlas/20230919170700.sql similarity index 100% rename from internal/services/catalog_write_service/db/migrations/atlas/20230919170700.sql rename to internal/services/catalogwriteservice/db/migrations/atlas/20230919170700.sql diff --git a/internal/services/catalog_write_service/db/migrations/atlas/atlas.sum b/internal/services/catalogwriteservice/db/migrations/atlas/atlas.sum similarity index 100% rename from internal/services/catalog_write_service/db/migrations/atlas/atlas.sum rename to internal/services/catalogwriteservice/db/migrations/atlas/atlas.sum diff --git a/internal/services/catalog_write_service/db/migrations/atlas/goose/00001_enable_uuid_extension.sql b/internal/services/catalogwriteservice/db/migrations/atlas/goose/00001_enable_uuid_extension.sql similarity index 100% rename from internal/services/catalog_write_service/db/migrations/atlas/goose/00001_enable_uuid_extension.sql rename to internal/services/catalogwriteservice/db/migrations/atlas/goose/00001_enable_uuid_extension.sql diff --git a/internal/services/catalog_write_service/db/migrations/atlas/goose/00002_create_products_table.sql b/internal/services/catalogwriteservice/db/migrations/atlas/goose/00002_create_products_table.sql similarity index 100% rename from internal/services/catalog_write_service/db/migrations/atlas/goose/00002_create_products_table.sql rename to internal/services/catalogwriteservice/db/migrations/atlas/goose/00002_create_products_table.sql diff --git a/internal/services/catalog_write_service/db/migrations/atlas/goose/atlas.sum b/internal/services/catalogwriteservice/db/migrations/atlas/goose/atlas.sum similarity index 100% rename from internal/services/catalog_write_service/db/migrations/atlas/goose/atlas.sum rename to internal/services/catalogwriteservice/db/migrations/atlas/goose/atlas.sum diff --git a/internal/services/catalog_write_service/db/migrations/atlas/readme.md b/internal/services/catalogwriteservice/db/migrations/atlas/readme.md similarity index 100% rename from internal/services/catalog_write_service/db/migrations/atlas/readme.md rename to internal/services/catalogwriteservice/db/migrations/atlas/readme.md diff --git a/internal/services/catalog_write_service/db/migrations/go-migrate/000001_enable_uuid_extension.down.sql b/internal/services/catalogwriteservice/db/migrations/go-migrate/000001_enable_uuid_extension.down.sql similarity index 100% rename from internal/services/catalog_write_service/db/migrations/go-migrate/000001_enable_uuid_extension.down.sql rename to internal/services/catalogwriteservice/db/migrations/go-migrate/000001_enable_uuid_extension.down.sql diff --git a/internal/services/catalog_write_service/db/migrations/go-migrate/000001_enable_uuid_extension.up.sql b/internal/services/catalogwriteservice/db/migrations/go-migrate/000001_enable_uuid_extension.up.sql similarity index 100% rename from internal/services/catalog_write_service/db/migrations/go-migrate/000001_enable_uuid_extension.up.sql rename to internal/services/catalogwriteservice/db/migrations/go-migrate/000001_enable_uuid_extension.up.sql diff --git a/internal/services/catalog_write_service/db/migrations/go-migrate/000002_create_products_table.down.sql b/internal/services/catalogwriteservice/db/migrations/go-migrate/000002_create_products_table.down.sql similarity index 100% rename from internal/services/catalog_write_service/db/migrations/go-migrate/000002_create_products_table.down.sql rename to internal/services/catalogwriteservice/db/migrations/go-migrate/000002_create_products_table.down.sql diff --git a/internal/services/catalog_write_service/db/migrations/go-migrate/000002_create_products_table.up.sql b/internal/services/catalogwriteservice/db/migrations/go-migrate/000002_create_products_table.up.sql similarity index 100% rename from internal/services/catalog_write_service/db/migrations/go-migrate/000002_create_products_table.up.sql rename to internal/services/catalogwriteservice/db/migrations/go-migrate/000002_create_products_table.up.sql diff --git a/internal/services/catalog_write_service/db/migrations/go-migrate/atlas.sum b/internal/services/catalogwriteservice/db/migrations/go-migrate/atlas.sum similarity index 100% rename from internal/services/catalog_write_service/db/migrations/go-migrate/atlas.sum rename to internal/services/catalogwriteservice/db/migrations/go-migrate/atlas.sum diff --git a/internal/services/catalog_write_service/db/migrations/go-migrate/readme.md b/internal/services/catalogwriteservice/db/migrations/go-migrate/readme.md similarity index 100% rename from internal/services/catalog_write_service/db/migrations/go-migrate/readme.md rename to internal/services/catalogwriteservice/db/migrations/go-migrate/readme.md diff --git a/internal/services/catalog_write_service/db/migrations/go-migrate/schema.sql b/internal/services/catalogwriteservice/db/migrations/go-migrate/schema.sql similarity index 100% rename from internal/services/catalog_write_service/db/migrations/go-migrate/schema.sql rename to internal/services/catalogwriteservice/db/migrations/go-migrate/schema.sql diff --git a/internal/services/catalog_write_service/db/migrations/goose-migrate/00001_enable_uuid_extension.sql b/internal/services/catalogwriteservice/db/migrations/goose-migrate/00001_enable_uuid_extension.sql similarity index 100% rename from internal/services/catalog_write_service/db/migrations/goose-migrate/00001_enable_uuid_extension.sql rename to internal/services/catalogwriteservice/db/migrations/goose-migrate/00001_enable_uuid_extension.sql diff --git a/internal/services/catalog_write_service/db/migrations/goose-migrate/00002_create_products_table.sql b/internal/services/catalogwriteservice/db/migrations/goose-migrate/00002_create_products_table.sql similarity index 100% rename from internal/services/catalog_write_service/db/migrations/goose-migrate/00002_create_products_table.sql rename to internal/services/catalogwriteservice/db/migrations/goose-migrate/00002_create_products_table.sql diff --git a/internal/services/catalog_write_service/db/migrations/goose-migrate/readme.md b/internal/services/catalogwriteservice/db/migrations/goose-migrate/readme.md similarity index 100% rename from internal/services/catalog_write_service/db/migrations/goose-migrate/readme.md rename to internal/services/catalogwriteservice/db/migrations/goose-migrate/readme.md diff --git a/internal/services/catalog_write_service/docs/docs.go b/internal/services/catalogwriteservice/docs/docs.go similarity index 100% rename from internal/services/catalog_write_service/docs/docs.go rename to internal/services/catalogwriteservice/docs/docs.go diff --git a/internal/services/catalog_write_service/docs/swagger.json b/internal/services/catalogwriteservice/docs/swagger.json similarity index 100% rename from internal/services/catalog_write_service/docs/swagger.json rename to internal/services/catalogwriteservice/docs/swagger.json diff --git a/internal/services/catalog_write_service/docs/swagger.yaml b/internal/services/catalogwriteservice/docs/swagger.yaml similarity index 100% rename from internal/services/catalog_write_service/docs/swagger.yaml rename to internal/services/catalogwriteservice/docs/swagger.yaml diff --git a/internal/services/catalog_write_service/go.mod b/internal/services/catalogwriteservice/go.mod similarity index 100% rename from internal/services/catalog_write_service/go.mod rename to internal/services/catalogwriteservice/go.mod diff --git a/internal/services/catalog_write_service/go.sum b/internal/services/catalogwriteservice/go.sum similarity index 100% rename from internal/services/catalog_write_service/go.sum rename to internal/services/catalogwriteservice/go.sum diff --git a/internal/services/catalog_write_service/internal/products/configurations/endpoints/endpoints.go b/internal/services/catalogwriteservice/internal/products/configurations/endpoints/endpoints.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/configurations/endpoints/endpoints.go rename to internal/services/catalogwriteservice/internal/products/configurations/endpoints/endpoints.go diff --git a/internal/services/catalog_write_service/internal/products/configurations/mappings/mapping_profile.go b/internal/services/catalogwriteservice/internal/products/configurations/mappings/mapping_profile.go similarity index 97% rename from internal/services/catalog_write_service/internal/products/configurations/mappings/mapping_profile.go rename to internal/services/catalogwriteservice/internal/products/configurations/mappings/mapping_profile.go index 466cee39..b3f47b90 100644 --- a/internal/services/catalog_write_service/internal/products/configurations/mappings/mapping_profile.go +++ b/internal/services/catalogwriteservice/internal/products/configurations/mappings/mapping_profile.go @@ -53,7 +53,7 @@ func ConfigureProductsMappings() error { err = mapper.CreateCustomMap( func(product *models.Product) *productsService.Product { return &productsService.Product{ - ProductId: product.ProductId.String(), + ProductId: product.Id.String(), Name: product.Name, Description: product.Description, Price: product.Price, diff --git a/internal/services/catalog_write_service/internal/products/configurations/mediator/mediator.go b/internal/services/catalogwriteservice/internal/products/configurations/mediator/mediator.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/configurations/mediator/mediator.go rename to internal/services/catalogwriteservice/internal/products/configurations/mediator/mediator.go diff --git a/internal/services/catalog_write_service/internal/products/configurations/products_module_configurator.go b/internal/services/catalogwriteservice/internal/products/configurations/products_module_configurator.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/configurations/products_module_configurator.go rename to internal/services/catalogwriteservice/internal/products/configurations/products_module_configurator.go diff --git a/internal/services/catalog_write_service/internal/products/configurations/rabbitmq/rabbitmq_configurations.go b/internal/services/catalogwriteservice/internal/products/configurations/rabbitmq/rabbitmq_configurations.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/configurations/rabbitmq/rabbitmq_configurations.go rename to internal/services/catalogwriteservice/internal/products/configurations/rabbitmq/rabbitmq_configurations.go diff --git a/internal/services/catalog_write_service/internal/products/contracts/product_repository.go b/internal/services/catalogwriteservice/internal/products/contracts/product_repository.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/contracts/product_repository.go rename to internal/services/catalogwriteservice/internal/products/contracts/product_repository.go diff --git a/internal/services/catalog_write_service/internal/products/data/models/product_data_model.go b/internal/services/catalogwriteservice/internal/products/data/models/product_data_model.go similarity index 56% rename from internal/services/catalog_write_service/internal/products/data/models/product_data_model.go rename to internal/services/catalogwriteservice/internal/products/data/models/product_data_model.go index a11b22a0..5b3281c4 100644 --- a/internal/services/catalog_write_service/internal/products/data/models/product_data_model.go +++ b/internal/services/catalogwriteservice/internal/products/data/models/product_data_model.go @@ -13,17 +13,17 @@ import ( // ProductDataModel data model type ProductDataModel struct { - gorm.Model - ProductId uuid.UUID `json:"productId" gorm:"primaryKey"` - Name string `json:"name"` - Description string `json:"description"` - Price float64 `json:"price"` - CreatedAt time.Time `json:"createdAt" gorm:"default:current_timestamp"` - UpdatedAt time.Time `json:"updatedAt"` + Id uuid.UUID `gorm:"primaryKey"` + Name string + Description string + Price float64 + CreatedAt time.Time `gorm:"default:current_timestamp"` + UpdatedAt time.Time + // for soft delete - https://gorm.io/docs/delete.html#Soft-Delete + gorm.DeletedAt } -// https://gorm.io/docs/conventions.html#TableName -// TableName overrides the table name used by ProductDataModel to `products` +// TableName overrides the table name used by ProductDataModel to `products` - https://gorm.io/docs/conventions.html#TableName func (p *ProductDataModel) TableName() string { return "products" } diff --git a/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go b/internal/services/catalogwriteservice/internal/products/data/repositories/pg_product_repository.go similarity index 92% rename from internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go rename to internal/services/catalogwriteservice/internal/products/data/repositories/pg_product_repository.go index 5c7462c7..9d3294fd 100644 --- a/internal/services/catalog_write_service/internal/products/data/repositories/pg_product_repository.go +++ b/internal/services/catalogwriteservice/internal/products/data/repositories/pg_product_repository.go @@ -107,7 +107,7 @@ func (p *postgresProductRepository) GetProductById( uuid uuid.UUID, ) (*models.Product, error) { ctx, span := p.tracer.Start(ctx, "postgresProductRepository.GetProductById") - span.SetAttributes(attribute2.String("ProductId", uuid.String())) + span.SetAttributes(attribute2.String("Id", uuid.String())) defer span.End() product, err := p.gormGenericRepository.GetById(ctx, uuid) @@ -132,7 +132,7 @@ func (p *postgresProductRepository) GetProductById( "product with id %s laoded", uuid.String(), ), - logger.Fields{"Product": product, "ProductId": uuid}, + logger.Fields{"Product": product, "Id": uuid}, ) return product, nil @@ -161,9 +161,9 @@ func (p *postgresProductRepository) CreateProduct( p.log.Infow( fmt.Sprintf( "product with id '%s' created", - product.ProductId, + product.Id, ), - logger.Fields{"Product": product, "ProductId": product.ProductId}, + logger.Fields{"Product": product, "Id": product.Id}, ) return product, nil @@ -183,7 +183,7 @@ func (p *postgresProductRepository) UpdateProduct( err, fmt.Sprintf( "error in updating product with id %s into the database.", - updateProduct.ProductId, + updateProduct.Id, ), ), ) @@ -196,11 +196,11 @@ func (p *postgresProductRepository) UpdateProduct( p.log.Infow( fmt.Sprintf( "product with id '%s' updated", - updateProduct.ProductId, + updateProduct.Id, ), logger.Fields{ - "Product": updateProduct, - "ProductId": updateProduct.ProductId, + "Product": updateProduct, + "Id": updateProduct.Id, }, ) @@ -212,7 +212,7 @@ func (p *postgresProductRepository) DeleteProductByID( uuid uuid.UUID, ) error { ctx, span := p.tracer.Start(ctx, "postgresProductRepository.UpdateProduct") - span.SetAttributes(attribute2.String("ProductId", uuid.String())) + span.SetAttributes(attribute2.String("Id", uuid.String())) defer span.End() err := p.gormGenericRepository.Delete(ctx, uuid) diff --git a/internal/services/catalog_write_service/internal/products/dtos/v1/fxparams/product_handler_params.go b/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams/product_handler_params.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/dtos/v1/fxparams/product_handler_params.go rename to internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams/product_handler_params.go diff --git a/internal/services/catalog_write_service/internal/products/dtos/v1/fxparams/product_route_params.go b/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams/product_route_params.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/dtos/v1/fxparams/product_route_params.go rename to internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams/product_route_params.go diff --git a/internal/services/catalog_write_service/internal/products/dtos/v1/product_dto.go b/internal/services/catalogwriteservice/internal/products/dtos/v1/product_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/dtos/v1/product_dto.go rename to internal/services/catalogwriteservice/internal/products/dtos/v1/product_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product.go b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product.go rename to internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product.go diff --git a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_endpoint.go b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product_endpoint.go similarity index 97% rename from internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_endpoint.go rename to internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product_endpoint.go index 99ebdceb..e5328a11 100644 --- a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_endpoint.go +++ b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product_endpoint.go @@ -4,7 +4,7 @@ import ( "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos" diff --git a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_handler.go b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product_handler.go similarity index 95% rename from internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_handler.go rename to internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product_handler.go index 9f39d665..d562fcd1 100644 --- a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/create_product_handler.go +++ b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product_handler.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" dtosv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" @@ -40,7 +40,7 @@ func (c *createProductHandler) Handle( command *CreateProduct, ) (*dtos.CreateProductResponseDto, error) { product := &models.Product{ - ProductId: command.ProductID, + Id: command.ProductID, Name: command.Name, Description: command.Description, Price: command.Price, @@ -83,7 +83,7 @@ func (c *createProductHandler) Handle( ) createProductResult = &dtos.CreateProductResponseDto{ - ProductID: product.ProductId, + ProductID: product.Id, } c.Log.Infow( @@ -92,7 +92,7 @@ func (c *createProductHandler) Handle( command.ProductID, ), logger.Fields{ - "ProductId": command.ProductID, + "Id": command.ProductID, "MessageId": productCreated.MessageId, }, ) diff --git a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/dtos/create_product_request_dto.go b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos/create_product_request_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/dtos/create_product_request_dto.go rename to internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos/create_product_request_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/dtos/create_product_response_dto.go b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos/create_product_response_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/dtos/create_product_response_dto.go rename to internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos/create_product_response_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/events/domainevents/.gitkeep b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/events/domainevents/.gitkeep similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/events/domainevents/.gitkeep rename to internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/events/domainevents/.gitkeep diff --git a/internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/events/integrationevents/product_created.go b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/events/integrationevents/product_created.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/creatingproduct/v1/events/integrationevents/product_created.go rename to internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/events/integrationevents/product_created.go diff --git a/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product.go b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product.go rename to internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product.go diff --git a/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product_endpoint.go b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_endpoint.go similarity index 97% rename from internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product_endpoint.go rename to internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_endpoint.go index 9fc67d00..20ea8e86 100644 --- a/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product_endpoint.go +++ b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_endpoint.go @@ -4,7 +4,7 @@ import ( "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/dtos" diff --git a/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product_handler.go b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_handler.go similarity index 95% rename from internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product_handler.go rename to internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_handler.go index 34ed91d6..716a6a85 100644 --- a/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/delete_product_handler.go +++ b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_handler.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/events/integrationevents" @@ -69,7 +69,7 @@ func (c *deleteProductHandler) Handle( "product with id '%s' deleted", command.ProductID, ), - logger.Fields{"ProductId": command.ProductID}, + logger.Fields{"Id": command.ProductID}, ) return &mediatr.Unit{}, err diff --git a/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/dtos/delete_product_request_dto.go b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/dtos/delete_product_request_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/dtos/delete_product_request_dto.go rename to internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/dtos/delete_product_request_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/events/integrationevents/product_deleted.go b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/events/integrationevents/product_deleted.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/deletingproduct/v1/events/integrationevents/product_deleted.go rename to internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/events/integrationevents/product_deleted.go diff --git a/internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/dtos/get_product_by_id_request_dto.go b/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/dtos/get_product_by_id_request_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/dtos/get_product_by_id_request_dto.go rename to internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/dtos/get_product_by_id_request_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/dtos/get_product_by_id_response_dto.go b/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/dtos/get_product_by_id_response_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/dtos/get_product_by_id_response_dto.go rename to internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/dtos/get_product_by_id_response_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/get_product_by_id.go b/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/get_product_by_id.go rename to internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id.go diff --git a/internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/get_product_by_id_endpoint.go b/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id_endpoint.go similarity index 97% rename from internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/get_product_by_id_endpoint.go rename to internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id_endpoint.go index 32f8337b..da25eeff 100644 --- a/internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/get_product_by_id_endpoint.go +++ b/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id_endpoint.go @@ -4,7 +4,7 @@ import ( "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/dtos" diff --git a/internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/get_product_by_id_handler.go b/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id_handler.go similarity index 94% rename from internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/get_product_by_id_handler.go rename to internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id_handler.go index 36b821cb..ac915b5a 100644 --- a/internal/services/catalog_write_service/internal/products/features/gettingproductbyid/v1/get_product_by_id_handler.go +++ b/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id_handler.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" @@ -55,7 +55,7 @@ func (c *GetProductByIDHandler) Handle( "product with id: {%s} fetched", query.ProductID, ), - logger.Fields{"ProductId": query.ProductID.String()}, + logger.Fields{"Id": query.ProductID.String()}, ) return &dtos.GetProductByIdResponseDto{Product: productDto}, nil diff --git a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/dtos/get_products_request_dto.go b/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/dtos/get_products_request_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/getting_products/v1/dtos/get_products_request_dto.go rename to internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/dtos/get_products_request_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/dtos/get_products_response_dto.go b/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/dtos/get_products_response_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/getting_products/v1/dtos/get_products_response_dto.go rename to internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/dtos/get_products_response_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products.go b/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/get_products.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products.go rename to internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/get_products.go diff --git a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_endpoint.go b/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/get_products_endpoint.go similarity index 94% rename from internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_endpoint.go rename to internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/get_products_endpoint.go index d1f3a701..272d0228 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_endpoint.go +++ b/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/get_products_endpoint.go @@ -4,10 +4,10 @@ import ( "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/dtos" "emperror.dev/errors" "github.com/labstack/echo/v4" diff --git a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_handler.go b/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/get_products_handler.go similarity index 89% rename from internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_handler.go rename to internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/get_products_handler.go index 352498e6..5c5c2499 100644 --- a/internal/services/catalog_write_service/internal/products/features/getting_products/v1/get_products_handler.go +++ b/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/get_products_handler.go @@ -4,13 +4,13 @@ import ( "context" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" dtosv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "github.com/mehdihadeli/go-mediatr" @@ -38,7 +38,7 @@ func (c *getProductsHandler) Handle( ctx context.Context, query *GetProducts, ) (*dtos.GetProductsResponseDto, error) { - products, err := postgresgorm.Paginate[*datamodel.ProductDataModel, *models.Product]( + products, err := helpers.Paginate[*datamodel.ProductDataModel, *models.Product]( ctx, query.ListQuery, c.CatalogsDBContext.DB, diff --git a/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/dtos/search_products_request_dto.go b/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/dtos/search_products_request_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/dtos/search_products_request_dto.go rename to internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/dtos/search_products_request_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/dtos/search_products_response_dto.go b/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/dtos/search_products_response_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/dtos/search_products_response_dto.go rename to internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/dtos/search_products_response_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products.go b/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products.go rename to internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products.go diff --git a/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products_endpoint.go b/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_endpoint.go similarity index 98% rename from internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products_endpoint.go rename to internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_endpoint.go index 75ffefeb..e4db7d5d 100644 --- a/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products_endpoint.go +++ b/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_endpoint.go @@ -4,7 +4,7 @@ import ( "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/dtos" diff --git a/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products_handler.go b/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_handler.go similarity index 97% rename from internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products_handler.go rename to internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_handler.go index 0547b99b..0970c9f7 100644 --- a/internal/services/catalog_write_service/internal/products/features/searchingproduct/v1/search_products_handler.go +++ b/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_handler.go @@ -7,8 +7,8 @@ import ( "strings" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" reflectionHelper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/reflectionhelper" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" diff --git a/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/dtos/update_product_request_dto.go b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/dtos/update_product_request_dto.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/dtos/update_product_request_dto.go rename to internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/dtos/update_product_request_dto.go diff --git a/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/events/integrationevents/product_updated.go b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/events/integrationevents/product_updated.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/events/integrationevents/product_updated.go rename to internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/events/integrationevents/product_updated.go diff --git a/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product.go b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product.go similarity index 100% rename from internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product.go rename to internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product.go diff --git a/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_endpoint.go b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_endpoint.go similarity index 97% rename from internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_endpoint.go rename to internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_endpoint.go index 452147c7..f036de7b 100644 --- a/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_endpoint.go +++ b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_endpoint.go @@ -4,7 +4,7 @@ import ( "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/dtos" diff --git a/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_handler.go b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_handler.go similarity index 96% rename from internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_handler.go rename to internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_handler.go index 3b02fcaa..b10819c1 100644 --- a/internal/services/catalog_write_service/internal/products/features/updatingproduct/v1/update_product_handler.go +++ b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_handler.go @@ -6,7 +6,7 @@ import ( "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" @@ -92,7 +92,7 @@ func (c *updateProductHandler) Handle( "product with id '%s' updated", command.ProductID, ), - logger.Fields{"ProductId": command.ProductID}, + logger.Fields{"Id": command.ProductID}, ) c.Log.Infow( diff --git a/internal/services/catalog_write_service/internal/products/models/product.go b/internal/services/catalogwriteservice/internal/products/models/product.go similarity index 90% rename from internal/services/catalog_write_service/internal/products/models/product.go rename to internal/services/catalogwriteservice/internal/products/models/product.go index a7251bb9..913c5a7a 100644 --- a/internal/services/catalog_write_service/internal/products/models/product.go +++ b/internal/services/catalogwriteservice/internal/products/models/product.go @@ -8,7 +8,7 @@ import ( // Product model type Product struct { - ProductId uuid.UUID + Id uuid.UUID Name string Description string Price float64 diff --git a/internal/services/catalog_write_service/internal/products/products_fx.go b/internal/services/catalogwriteservice/internal/products/products_fx.go similarity index 98% rename from internal/services/catalog_write_service/internal/products/products_fx.go rename to internal/services/catalogwriteservice/internal/products/products_fx.go index 19839f9c..72bde291 100644 --- a/internal/services/catalog_write_service/internal/products/products_fx.go +++ b/internal/services/catalogwriteservice/internal/products/products_fx.go @@ -3,12 +3,12 @@ package products import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/repositories" creatingproductv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1" deletingproductv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1" - gettingproductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1" gettingproductbyidv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1" + gettingproductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1" searchingproductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1" updatingoroductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/grpc" diff --git a/internal/services/catalog_write_service/internal/shared/app/app.go b/internal/services/catalogwriteservice/internal/shared/app/app.go similarity index 100% rename from internal/services/catalog_write_service/internal/shared/app/app.go rename to internal/services/catalogwriteservice/internal/shared/app/app.go diff --git a/internal/services/catalog_write_service/internal/shared/app/application.go b/internal/services/catalogwriteservice/internal/shared/app/application.go similarity index 100% rename from internal/services/catalog_write_service/internal/shared/app/application.go rename to internal/services/catalogwriteservice/internal/shared/app/application.go diff --git a/internal/services/catalog_write_service/internal/shared/app/application_builder.go b/internal/services/catalogwriteservice/internal/shared/app/application_builder.go similarity index 100% rename from internal/services/catalog_write_service/internal/shared/app/application_builder.go rename to internal/services/catalogwriteservice/internal/shared/app/application_builder.go diff --git a/internal/services/catalog_write_service/internal/shared/app/test/test_app.go b/internal/services/catalogwriteservice/internal/shared/app/test/test_app.go similarity index 96% rename from internal/services/catalog_write_service/internal/shared/app/test/test_app.go rename to internal/services/catalogwriteservice/internal/shared/app/test/test_app.go index 7e84e89f..096cb737 100644 --- a/internal/services/catalog_write_service/internal/shared/app/test/test_app.go +++ b/internal/services/catalogwriteservice/internal/shared/app/test/test_app.go @@ -8,7 +8,7 @@ import ( fxcontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc" - config3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/config" + config3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" contracts2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/contracts" gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" @@ -62,12 +62,12 @@ func (a *TestApp) Run(t *testing.T) (result *TestAppResult) { err := testApp.ConfigureCatalogs() if err != nil { - testApp.Logger().Fatalf("Error in ConfigureCatalogs", err) + testApp.Logger().Fatalf("Error in ConfigureCatalogs, %s", err) } err = testApp.MapCatalogsEndpoints() if err != nil { - testApp.Logger().Fatalf("Error in MapCatalogsEndpoints", err) + testApp.Logger().Fatalf("Error in MapCatalogsEndpoints, %s", err) } testApp.ResolveFunc( diff --git a/internal/services/catalog_write_service/internal/shared/app/test/test_application.go b/internal/services/catalogwriteservice/internal/shared/app/test/test_application.go similarity index 100% rename from internal/services/catalog_write_service/internal/shared/app/test/test_application.go rename to internal/services/catalogwriteservice/internal/shared/app/test/test_application.go diff --git a/internal/services/catalog_write_service/internal/shared/app/test/test_application_builder.go b/internal/services/catalogwriteservice/internal/shared/app/test/test_application_builder.go similarity index 100% rename from internal/services/catalog_write_service/internal/shared/app/test/test_application_builder.go rename to internal/services/catalogwriteservice/internal/shared/app/test/test_application_builder.go diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator.go b/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator.go similarity index 86% rename from internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator.go rename to internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator.go index 44145d2f..5aa27dc3 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator.go +++ b/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator.go @@ -4,8 +4,9 @@ import ( "fmt" "net/http" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" - echocontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" + echocontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/contracts" migrationcontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations" @@ -44,12 +45,19 @@ func (ic *CatalogsServiceConfigurator) ConfigureCatalogs() error { // Shared // Catalogs configurations ic.ResolveFunc( - func(gorm *gorm.DB, postgresMigrationRunner migrationcontracts.PostgresMigrationRunner) error { - err := ic.migrateCatalogs(gorm, postgresMigrationRunner) + func(db *gorm.DB, postgresMigrationRunner migrationcontracts.PostgresMigrationRunner) error { + err := ic.migrateCatalogs(postgresMigrationRunner) if err != nil { return err } + if ic.Environment() != environment.Test { + err = ic.seedCatalogs(db) + if err != nil { + return err + } + } + return nil }, ) diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator_migration.go b/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator_migration.go similarity index 72% rename from internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator_migration.go rename to internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator_migration.go index fea9b6c4..599fcba2 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator_migration.go +++ b/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator_migration.go @@ -4,30 +4,37 @@ import ( "context" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "gorm.io/gorm" ) func (ic *CatalogsServiceConfigurator) migrateCatalogs( - gorm *gorm.DB, runner contracts.PostgresMigrationRunner, ) error { // - for complex migration and ability to back-track to specific migration revision it is better we use `goose`, but if we want to use built-in gorm migration we can also sync gorm with `atlas` integration migration versioning for getting migration history from grom changes // - here I used goose for migration, with using cmd/migration file - // https://atlasgo.io/guides/orms/gorm - //err := gorm.AutoMigrate(&models.Product{}) - //if err != nil { - // return err - //} // migration with Goorse - return ic.migrateGoose(runner) + return migrateGoose(runner) } -func (ic *CatalogsServiceConfigurator) migrateGoose( +func migrateGoose( runner contracts.PostgresMigrationRunner, ) error { err := runner.Up(context.Background(), 0) return err } + +func migrateGorm( + db *gorm.DB, +) error { + // https://atlasgo.io/guides/orms/gorm + err := db.AutoMigrate(&models.Product{}) + if err != nil { + return err + } + + return nil +} diff --git a/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator_seed.go b/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator_seed.go new file mode 100644 index 00000000..fec85dc7 --- /dev/null +++ b/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator_seed.go @@ -0,0 +1,104 @@ +package catalogs + +import ( + "time" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/testfixture" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" + + "emperror.dev/errors" + "github.com/brianvoe/gofakeit/v6" + uuid "github.com/satori/go.uuid" + "gorm.io/gorm" +) + +func (ic *CatalogsServiceConfigurator) seedCatalogs( + db *gorm.DB, +) error { + err := seedDataManually(db) + if err != nil { + return err + } + + return nil +} + +func seedDataManually(gormDB *gorm.DB) error { + var count int64 + + // https://gorm.io/docs/advanced_query.html#Count + gormDB.Model(&datamodel.ProductDataModel{}).Count(&count) + if count > 0 { + return nil + } + + products := []*datamodel.ProductDataModel{ + { + Id: uuid.NewV4(), + Name: gofakeit.Name(), + CreatedAt: time.Now(), + Description: gofakeit.AdjectiveDescriptive(), + Price: gofakeit.Price(100, 1000), + }, + { + Id: uuid.NewV4(), + Name: gofakeit.Name(), + CreatedAt: time.Now(), + Description: gofakeit.AdjectiveDescriptive(), + Price: gofakeit.Price(100, 1000), + }, + } + + err := gormDB.CreateInBatches(products, len(products)).Error + if err != nil { + return errors.Wrap(err, "error in seed database") + } + + return nil +} + +func seedDataWithFixture(gormDB *gorm.DB) error { + var count int64 + + // https://gorm.io/docs/advanced_query.html#Count + gormDB.Model(&datamodel.ProductDataModel{}).Count(&count) + if count > 0 { + return nil + } + + db, err := gormDB.DB() + if err != nil { + return errors.WrapIf(err, "error in seed database") + } + + // https://github.com/go-testfixtures/testfixtures#templating + // seed data + var data []struct { + Name string + ProductId uuid.UUID + Description string + } + + f := []struct { + Name string + ProductId uuid.UUID + Description string + }{ + {gofakeit.Name(), uuid.NewV4(), gofakeit.AdjectiveDescriptive()}, + {gofakeit.Name(), uuid.NewV4(), gofakeit.AdjectiveDescriptive()}, + } + + data = append(data, f...) + + err = testfixture.RunPostgresFixture( + db, + []string{"db/fixtures/products"}, + map[string]interface{}{ + "Products": data, + }) + if err != nil { + return errors.WrapIf(err, "error in seed database") + } + + return nil +} diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go b/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go similarity index 94% rename from internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go rename to internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go index e45480b9..c5ff5a76 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go +++ b/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator_swagger.go @@ -1,7 +1,7 @@ package catalogs import ( - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/docs" "github.com/labstack/echo/v4" diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_fx.go b/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_fx.go similarity index 100% rename from internal/services/catalog_write_service/internal/shared/configurations/catalogs/catalogs_fx.go rename to internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_fx.go diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go b/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go similarity index 100% rename from internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go rename to internal/services/catalogwriteservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go diff --git a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go b/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go similarity index 98% rename from internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go rename to internal/services/catalogwriteservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go index 0d234de6..b64b65d1 100644 --- a/internal/services/catalog_write_service/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go +++ b/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_fx.go @@ -4,7 +4,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health" - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/goose" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" diff --git a/internal/services/catalog_write_service/internal/shared/contracts/catalogs_metrics.go b/internal/services/catalogwriteservice/internal/shared/contracts/catalogs_metrics.go similarity index 100% rename from internal/services/catalog_write_service/internal/shared/contracts/catalogs_metrics.go rename to internal/services/catalogwriteservice/internal/shared/contracts/catalogs_metrics.go diff --git a/internal/services/catalog_write_service/internal/shared/data/data_fx.go b/internal/services/catalogwriteservice/internal/shared/data/data_fx.go similarity index 100% rename from internal/services/catalog_write_service/internal/shared/data/data_fx.go rename to internal/services/catalogwriteservice/internal/shared/data/data_fx.go diff --git a/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext.go b/internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext.go similarity index 85% rename from internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext.go rename to internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext.go index 1e29da56..9b261b02 100644 --- a/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext.go +++ b/internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext.go @@ -4,10 +4,11 @@ import ( "context" "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/scopes" datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" @@ -101,20 +102,30 @@ func (c *CatalogsGormDBContext) RunInTx( // Extensions for shared and reusable methods. for complex and none-reusable queries we use DBContext directly +func (c *CatalogsGormDBContext) ExistsProduct( + ctx context.Context, + id uuid.UUID, +) bool { + var count int64 + + c.WithContext(ctx).Model(&datamodel.ProductDataModel{}).Scopes(scopes.FilterByID(id)).Count(&count) + + return count > 0 +} + func (c *CatalogsGormDBContext) FindProductByID( ctx context.Context, id uuid.UUID, ) (*models.Product, error) { - var productDatas []*datamodel.ProductDataModel var productData *datamodel.ProductDataModel - s := c.DB.WithContext(ctx).Find(&productDatas).Error - fmt.Println(s) - // https://gorm.io/docs/query.html#Retrieving-objects-with-primary-key // https://gorm.io/docs/query.html#Struct-amp-Map-Conditions // https://gorm.io/docs/query.html#Inline-Condition // https://gorm.io/docs/advanced_query.html + // result := c.WithContext(ctx).First(&productData, "id = ?", id) + // result := c.WithContext(ctx).First(&datamodel.ProductDataModel{Id: id}) + // result := c.WithContext(ctx).Scopes(scopes.FilterByID(id)).First(&productData) result := c.WithContext(ctx).First(&productData, id) if result.Error != nil { return nil, customErrors.NewNotFoundErrorWrap( @@ -146,26 +157,17 @@ func (c *CatalogsGormDBContext) DeleteProductByID( ) error { dbContext := c.WithTxIfExists(ctx) - product, err := dbContext.FindProductByID(ctx, id) - if err != nil { - return customErrors.NewNotFoundErrorWrap( - err, - fmt.Sprintf( - "product with id `%s` not found in the database", - id.String(), - ), - ) - } - - productDataModel, err := mapper.Map[*datamodel.ProductDataModel](product) - if err != nil { - return customErrors.NewInternalServerErrorWrap( - err, - "error in the mapping ProductDataModel", - ) + exists := c.ExistsProduct(ctx, id) + if !exists { + return customErrors.NewNotFoundError(fmt.Sprintf("product with id `%s` not found in the database", + id.String(), + )) } - result := dbContext.WithContext(ctx).Delete(productDataModel, id) + // https://gorm.io/docs/delete.html#Delete-a-Record + // https://gorm.io/docs/delete.html#Find-soft-deleted-records + // result := dbContext.WithContext(ctx).Delete(&datamodel.ProductDataModel{Id: id}) + result := dbContext.WithContext(ctx).Delete(&datamodel.ProductDataModel{}, id) if result.Error != nil { return customErrors.NewInternalServerErrorWrap( result.Error, diff --git a/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext_test.go b/internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext_test.go similarity index 67% rename from internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext_test.go rename to internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext_test.go index 350e6f9e..58509af2 100644 --- a/internal/services/catalog_write_service/internal/shared/data/dbcontext/catalogs_dbcontext_test.go +++ b/internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext_test.go @@ -1,17 +1,21 @@ +//go:build unit +// +build unit + package dbcontext import ( "context" + "os" "testing" "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/migration/goose" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/scopes" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations/mappings" datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" @@ -28,9 +32,10 @@ import ( // Define the suite type DBContextTestSuite struct { suite.Suite - items []*datamodel.ProductDataModel - dbContext *CatalogsGormDBContext - app *fxtest.App + items []*datamodel.ProductDataModel + dbContext *CatalogsGormDBContext + app *fxtest.App + dbFilePath string } // In order for 'go test' to run this suite, we need to create @@ -42,7 +47,7 @@ func TestDBContextTestSuite(t *testing.T) { func (s *DBContextTestSuite) Test_FindProductByID() { s.Require().NotNil(s.dbContext) - id := s.items[0].ProductId + id := s.items[0].Id p, err := s.dbContext.FindProductByID( context.Background(), @@ -51,13 +56,37 @@ func (s *DBContextTestSuite) Test_FindProductByID() { s.Require().NoError(err) s.Require().NotNil(p) - s.Assert().Equal(p.ProductId, id) + s.Assert().Equal(p.Id, id) +} + +func (s *DBContextTestSuite) Test_ExistsProductByID() { + s.Require().NotNil(s.dbContext) + + id := s.items[0].Id + + exist := s.dbContext.ExistsProduct( + context.Background(), + id, + ) + s.Require().True(exist) +} + +func (s *DBContextTestSuite) Test_NoneExistsProductByID() { + s.Require().NotNil(s.dbContext) + + id := uuid.NewV4() + + exist := s.dbContext.ExistsProduct( + context.Background(), + id, + ) + s.Require().False(exist) } func (s *DBContextTestSuite) Test_DeleteProductByID() { s.Require().NotNil(s.dbContext) - id := s.items[0].ProductId + id := s.items[0].Id err := s.dbContext.DeleteProductByID( context.Background(), @@ -69,16 +98,30 @@ func (s *DBContextTestSuite) Test_DeleteProductByID() { context.Background(), id, ) - - s.Require().Nil(p) s.Require().Error(err) + s.Require().Nil(p) + + // https://gorm.io/docs/delete.html#Find-soft-deleted-records + var softDeletedProduct *datamodel.ProductDataModel + s.dbContext.Scopes(scopes.FilterAllItemsWithSoftDeleted).First(&softDeletedProduct, id) + s.Require().NotNil(softDeletedProduct) + + var deletedCount int64 + var allCount int64 + + // https://gorm.io/docs/advanced_query.html#Count + s.dbContext.Model(&datamodel.ProductDataModel{}).Scopes(scopes.FilterAllItemsWithSoftDeleted).Count(&allCount) + s.Equal(allCount, int64(2)) + + s.dbContext.Model(&datamodel.ProductDataModel{}).Scopes(scopes.SoftDeleted).Count(&deletedCount) + s.Equal(deletedCount, int64(1)) } func (s *DBContextTestSuite) Test_CreateProduct() { s.Require().NotNil(s.dbContext) item := &models.Product{ - ProductId: uuid.NewV4(), + Id: uuid.NewV4(), Name: gofakeit.Name(), Description: gofakeit.AdjectiveDescriptive(), Price: gofakeit.Price(100, 1000), @@ -89,19 +132,19 @@ func (s *DBContextTestSuite) Test_CreateProduct() { p, err := s.dbContext.FindProductByID( context.Background(), - item.ProductId, + item.Id, ) s.Require().NoError(err) s.Require().NotNil(p) - s.Assert().Equal(p.ProductId, item.ProductId) - s.Assert().Equal(p.ProductId, res.ProductId) + s.Assert().Equal(p.Id, item.Id) + s.Assert().Equal(p.Id, res.Id) } func (s *DBContextTestSuite) Test_UpdateProduct() { s.Require().NotNil(s.dbContext) - id := s.items[0].ProductId + id := s.items[0].Id p, err := s.dbContext.FindProductByID( context.Background(), @@ -127,51 +170,66 @@ func (s *DBContextTestSuite) Test_UpdateProduct() { } // TestSuite Hooks + func (s *DBContextTestSuite) SetupTest() { + err := mappings.ConfigureProductsMappings() + s.Require().NoError(err) + var gormDBContext *CatalogsGormDBContext + var gormOptions *gormPostgres.GormOptions app := fxtest.New( s.T(), config.ModuleFunc(environment.Test), zap.Module, fxlog.FxLogger, - core.Module, gormPostgres.Module, - goose.Module, fx.Decorate( func(cfg *gormPostgres.GormOptions) (*gormPostgres.GormOptions, error) { - // using sql-lite in-memory - cfg.UseInMemory = true + // using sql-lite with a database file + cfg.UseSQLLite = true return cfg, nil }, ), - fx.Provide( - NewCatalogsDBContext, - ), + fx.Provide(NewCatalogsDBContext), fx.Populate(&gormDBContext), + fx.Populate(&gormOptions), ).RequireStart() + s.app = app s.dbContext = gormDBContext - products := s.setupInMemoryContext() + s.dbFilePath = gormOptions.Dns() - s.app = app - s.items = products + s.initDB() } -func (s *DBContextTestSuite) SetupSuite() { - err := mappings.ConfigureProductsMappings() +func (s *DBContextTestSuite) TearDownTest() { + err := s.cleanupDB() s.Require().NoError(err) + + mapper.ClearMappings() } -func (s *DBContextTestSuite) setupInMemoryContext() []*datamodel.ProductDataModel { +func (s *DBContextTestSuite) initDB() { err := migrateGorm(s.dbContext.DB) s.Require().NoError(err) - res, err := seedData(s.dbContext.DB) - s.Require().NoError(errors.WrapIf(err, "error in seeding data in postgres")) + products, err := seedData(s.dbContext.DB) + s.Require().NoError(err) + + s.items = products +} + +func (s *DBContextTestSuite) cleanupDB() error { + sqldb, _ := s.dbContext.DB.DB() + e := sqldb.Close() + s.Require().NoError(e) + + // removing sql-lite file + err := os.Remove(s.dbFilePath) - return res + return err } func migrateGorm(db *gorm.DB) error { @@ -186,14 +244,14 @@ func migrateGorm(db *gorm.DB) error { func seedData(gormDB *gorm.DB) ([]*datamodel.ProductDataModel, error) { products := []*datamodel.ProductDataModel{ { - ProductId: uuid.NewV4(), + Id: uuid.NewV4(), Name: gofakeit.Name(), CreatedAt: time.Now(), Description: gofakeit.AdjectiveDescriptive(), Price: gofakeit.Price(100, 1000), }, { - ProductId: uuid.NewV4(), + Id: uuid.NewV4(), Name: gofakeit.Name(), CreatedAt: time.Now(), Description: gofakeit.AdjectiveDescriptive(), diff --git a/internal/services/catalogwriteservice/internal/shared/data/scopes/scopes.go b/internal/services/catalogwriteservice/internal/shared/data/scopes/scopes.go new file mode 100644 index 00000000..76877700 --- /dev/null +++ b/internal/services/catalogwriteservice/internal/shared/data/scopes/scopes.go @@ -0,0 +1,3 @@ +package scopes + +// After scopes, we should have a runner function like Find, Update, Delete diff --git a/internal/services/catalog_write_service/internal/shared/grpc/genproto/products.pb.go b/internal/services/catalogwriteservice/internal/shared/grpc/genproto/products.pb.go similarity index 95% rename from internal/services/catalog_write_service/internal/shared/grpc/genproto/products.pb.go rename to internal/services/catalogwriteservice/internal/shared/grpc/genproto/products.pb.go index 78f454d3..7129f4a8 100644 --- a/internal/services/catalog_write_service/internal/shared/grpc/genproto/products.pb.go +++ b/internal/services/catalogwriteservice/internal/shared/grpc/genproto/products.pb.go @@ -2,16 +2,17 @@ // versions: // protoc-gen-go v1.26.0 // protoc v4.23.4 -// source: catalog_write_service/products.proto +// source: catalogwriteservice/products.proto package products_service import ( + reflect "reflect" + sync "sync" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" ) const ( @@ -26,7 +27,7 @@ type Product struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ProductId string `protobuf:"bytes,1,opt,name=ProductId,proto3" json:"ProductId,omitempty"` + ProductId string `protobuf:"bytes,1,opt,name=Id,proto3" json:"Id,omitempty"` Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` Description string `protobuf:"bytes,3,opt,name=Description,proto3" json:"Description,omitempty"` Price float64 `protobuf:"fixed64,4,opt,name=Price,proto3" json:"Price,omitempty"` @@ -176,7 +177,7 @@ type CreateProductRes struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ProductId string `protobuf:"bytes,1,opt,name=ProductId,proto3" json:"ProductId,omitempty"` + ProductId string `protobuf:"bytes,1,opt,name=Id,proto3" json:"Id,omitempty"` } func (x *CreateProductRes) Reset() { @@ -223,7 +224,7 @@ type UpdateProductReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ProductId string `protobuf:"bytes,1,opt,name=ProductId,proto3" json:"ProductId,omitempty"` + ProductId string `protobuf:"bytes,1,opt,name=Id,proto3" json:"Id,omitempty"` Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` Description string `protobuf:"bytes,3,opt,name=Description,proto3" json:"Description,omitempty"` Price float64 `protobuf:"fixed64,4,opt,name=Price,proto3" json:"Price,omitempty"` @@ -332,7 +333,7 @@ type GetProductByIdReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ProductId string `protobuf:"bytes,1,opt,name=ProductId,proto3" json:"ProductId,omitempty"` + ProductId string `protobuf:"bytes,1,opt,name=Id,proto3" json:"Id,omitempty"` } func (x *GetProductByIdReq) Reset() { @@ -505,17 +506,19 @@ func file_catalog_write_service_products_proto_rawDescGZIP() []byte { return file_catalog_write_service_products_proto_rawDescData } -var file_catalog_write_service_products_proto_msgTypes = make([]protoimpl.MessageInfo, 7) -var file_catalog_write_service_products_proto_goTypes = []interface{}{ - (*Product)(nil), // 0: products_service.Product - (*CreateProductReq)(nil), // 1: products_service.CreateProductReq - (*CreateProductRes)(nil), // 2: products_service.CreateProductRes - (*UpdateProductReq)(nil), // 3: products_service.UpdateProductReq - (*UpdateProductRes)(nil), // 4: products_service.UpdateProductRes - (*GetProductByIdReq)(nil), // 5: products_service.GetProductByIdReq - (*GetProductByIdRes)(nil), // 6: products_service.GetProductByIdRes - (*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp -} +var ( + file_catalog_write_service_products_proto_msgTypes = make([]protoimpl.MessageInfo, 7) + file_catalog_write_service_products_proto_goTypes = []interface{}{ + (*Product)(nil), // 0: products_service.Product + (*CreateProductReq)(nil), // 1: products_service.CreateProductReq + (*CreateProductRes)(nil), // 2: products_service.CreateProductRes + (*UpdateProductReq)(nil), // 3: products_service.UpdateProductReq + (*UpdateProductRes)(nil), // 4: products_service.UpdateProductRes + (*GetProductByIdReq)(nil), // 5: products_service.GetProductByIdReq + (*GetProductByIdRes)(nil), // 6: products_service.GetProductByIdRes + (*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp + } +) var file_catalog_write_service_products_proto_depIdxs = []int32{ 7, // 0: products_service.Product.CreatedAt:type_name -> google.protobuf.Timestamp 7, // 1: products_service.Product.UpdatedAt:type_name -> google.protobuf.Timestamp diff --git a/internal/services/catalog_write_service/internal/shared/grpc/genproto/products_grpc.pb.go b/internal/services/catalogwriteservice/internal/shared/grpc/genproto/products_grpc.pb.go similarity index 98% rename from internal/services/catalog_write_service/internal/shared/grpc/genproto/products_grpc.pb.go rename to internal/services/catalogwriteservice/internal/shared/grpc/genproto/products_grpc.pb.go index e8174210..e509ba2d 100644 --- a/internal/services/catalog_write_service/internal/shared/grpc/genproto/products_grpc.pb.go +++ b/internal/services/catalogwriteservice/internal/shared/grpc/genproto/products_grpc.pb.go @@ -2,7 +2,7 @@ // versions: // - protoc-gen-go-grpc v1.3.0 // - protoc v4.23.4 -// source: catalog_write_service/products.proto +// source: catalogwriteservice/products.proto package products_service @@ -177,5 +177,5 @@ var ProductsService_ServiceDesc = grpc.ServiceDesc{ }, }, Streams: []grpc.StreamDesc{}, - Metadata: "catalog_write_service/products.proto", + Metadata: "catalogwriteservice/products.proto", } diff --git a/internal/services/catalog_write_service/internal/shared/grpc/product_grpc_service_server.go b/internal/services/catalogwriteservice/internal/shared/grpc/product_grpc_service_server.go similarity index 97% rename from internal/services/catalog_write_service/internal/shared/grpc/product_grpc_service_server.go rename to internal/services/catalogwriteservice/internal/shared/grpc/product_grpc_service_server.go index 094d7c98..4531b406 100644 --- a/internal/services/catalog_write_service/internal/shared/grpc/product_grpc_service_server.go +++ b/internal/services/catalogwriteservice/internal/shared/grpc/product_grpc_service_server.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" @@ -87,7 +87,7 @@ func (s *ProductGrpcServiceServer) CreateProduct( command.ProductID, err, ), - logger.Fields{"ProductId": command.ProductID}, + logger.Fields{"Id": command.ProductID}, ) return nil, err } @@ -151,7 +151,7 @@ func (s *ProductGrpcServiceServer) UpdateProduct( command.ProductID, err, ), - logger.Fields{"ProductId": command.ProductID}, + logger.Fields{"Id": command.ProductID}, ) return nil, err } @@ -216,7 +216,7 @@ func (s *ProductGrpcServiceServer) GetProductById( query.ProductID, err, ), - logger.Fields{"ProductId": query.ProductID}, + logger.Fields{"Id": query.ProductID}, ) return nil, err } diff --git a/internal/services/catalog_write_service/internal/shared/testfixtures/integration/integration_test_fixture.go b/internal/services/catalogwriteservice/internal/shared/testfixtures/integration/integration_test_fixture.go similarity index 92% rename from internal/services/catalog_write_service/internal/shared/testfixtures/integration/integration_test_fixture.go rename to internal/services/catalogwriteservice/internal/shared/testfixtures/integration/integration_test_fixture.go index c2f72913..4bf67f8c 100644 --- a/internal/services/catalog_write_service/internal/shared/testfixtures/integration/integration_test_fixture.go +++ b/internal/services/catalogwriteservice/internal/shared/testfixtures/integration/integration_test_fixture.go @@ -8,7 +8,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/bus" fxcontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" config2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/testfixture" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" @@ -78,8 +78,9 @@ func NewIntegrationTestSharedFixture( func (i *IntegrationTestSharedFixture) SetupTest() { i.Log.Info("SetupTest started") - // seed data in each test - res, err := seedData(i.Gorm) + // migration will do in app configuration + // seed data for our tests - app seed doesn't run in test environment + res, err := seedDataManually(i.Gorm) if err != nil { i.Log.Error(errors.WrapIf(err, "error in seeding data in postgres")) } @@ -135,17 +136,17 @@ func (i *IntegrationTestSharedFixture) cleanupPostgresData() error { return nil } -func seedData(gormDB *gorm.DB) ([]*datamodel.ProductDataModel, error) { +func seedDataManually(gormDB *gorm.DB) ([]*datamodel.ProductDataModel, error) { products := []*datamodel.ProductDataModel{ { - ProductId: uuid.NewV4(), + Id: uuid.NewV4(), Name: gofakeit.Name(), CreatedAt: time.Now(), Description: gofakeit.AdjectiveDescriptive(), Price: gofakeit.Price(100, 1000), }, { - ProductId: uuid.NewV4(), + Id: uuid.NewV4(), Name: gofakeit.Name(), CreatedAt: time.Now(), Description: gofakeit.AdjectiveDescriptive(), @@ -153,8 +154,6 @@ func seedData(gormDB *gorm.DB) ([]*datamodel.ProductDataModel, error) { }, } - // migration will do in app configuration - // seed data err := gormDB.CreateInBatches(products, len(products)).Error if err != nil { return nil, errors.Wrap(err, "error in seed database") @@ -163,13 +162,7 @@ func seedData(gormDB *gorm.DB) ([]*datamodel.ProductDataModel, error) { return products, nil } -func seedAndMigration(gormDB *gorm.DB) ([]*datamodel.ProductDataModel, error) { - // migration - err := gormDB.AutoMigrate(datamodel.ProductDataModel{}) - if err != nil { - return nil, errors.WrapIf(err, "error in seed database") - } - +func seedDataWithFixture(gormDB *gorm.DB) ([]*datamodel.ProductDataModel, error) { db, err := gormDB.DB() if err != nil { return nil, errors.WrapIf(err, "error in seed database") @@ -209,5 +202,6 @@ func seedAndMigration(gormDB *gorm.DB) ([]*datamodel.ProductDataModel, error) { utils.NewListQuery(10, 1), gormDB, ) + return result.Items, nil } diff --git a/internal/services/catalog_write_service/internal/shared/testfixtures/unittest/unit_test_fixture.go b/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest/unit_test_fixture.go similarity index 71% rename from internal/services/catalog_write_service/internal/shared/testfixtures/unittest/unit_test_fixture.go rename to internal/services/catalogwriteservice/internal/shared/testfixtures/unittest/unit_test_fixture.go index 32778f03..17ec3d71 100644 --- a/internal/services/catalog_write_service/internal/shared/testfixtures/unittest/unit_test_fixture.go +++ b/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest/unit_test_fixture.go @@ -2,14 +2,13 @@ package unittest import ( "context" - "fmt" "os" "path/filepath" "testing" "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" - mocks3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/mocks" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/mocks" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/gromlog" @@ -35,11 +34,11 @@ type UnitTestSharedFixture struct { Log logger.Logger suite.Suite Products []*datamodel.ProductDataModel - Bus *mocks3.Bus + Bus *mocks.Bus Tracer trace.Tracer CatalogDBContext *dbcontext.CatalogsGormDBContext Ctx context.Context - projectRootDir string + dbFilePath string dbFileName string } @@ -62,104 +61,114 @@ func NewUnitTestSharedFixture(t *testing.T) *UnitTestSharedFixture { return unit } -// Shared Hooks +func (c *UnitTestSharedFixture) BeginTx() { + c.Log.Info("starting transaction") + // seems when we `Begin` a transaction on gorm.DB (with SQLLite in-memory) our previous gormDB before transaction will remove and the new gormDB with tx will go on the memory + tx := c.CatalogDBContext.Begin() + gormContext := helpers.SetTxToContext(c.Ctx, tx) + c.Ctx = gormContext + + //// works on both transaction and none-transactional dbcontext + //var productData []*datamodel.ProductDataModel + //var productData2 []*datamodel.ProductDataModel + // + //s := c.CatalogDBContext.Find(&productData).Error + //s2 := tx.Find(&productData2).Error +} + +func (c *UnitTestSharedFixture) CommitTx() { + tx := helpers.GetTxFromContextIfExists(c.Ctx) + if tx != nil { + c.Log.Info("committing transaction") + tx.Commit() + } +} + +/// Shared Hooks + +func (c *UnitTestSharedFixture) SetupSuite() { + // this fix root working directory problem in our test environment inner our fixture + environment.FixProjectRootWorkingDirectoryPath() + projectRootDir := environment.GetProjectRootWorkingDirectory() + + c.dbFilePath = filepath.Join(projectRootDir, c.dbFileName) +} + +func (c *UnitTestSharedFixture) TearDownSuite() { +} func (c *UnitTestSharedFixture) SetupTest() { ctx := context.Background() c.Ctx = ctx - // create new mocks - bus := &mocks3.Bus{} + c.setupBus() - bus.On("PublishMessage", mock.Anything, mock.Anything, mock.Anything). - Return(nil) - - dbContext, products := c.createSQLLiteDBContext() - - c.Bus = bus - c.CatalogDBContext = dbContext - c.Products = products + c.setupDB() err := mappings.ConfigureProductsMappings() c.Require().NoError(err) } func (c *UnitTestSharedFixture) TearDownTest() { - err := c.dropSQLLiteDB() + err := c.cleanupDB() c.Require().NoError(err) + mapper.ClearMappings() } -func (c *UnitTestSharedFixture) SetupSuite() { - environment.FixProjectRootWorkingDirectoryPath() - c.projectRootDir = environment.GetProjectRootWorkingDirectory() -} +func (c *UnitTestSharedFixture) setupBus() { + // create new mocks + bus := &mocks.Bus{} -func (c *UnitTestSharedFixture) TearDownSuite() { + bus.On("PublishMessage", mock.Anything, mock.Anything, mock.Anything). + Return(nil) + c.Bus = bus } -func (c *UnitTestSharedFixture) createSQLLiteDBContext() (*dbcontext.CatalogsGormDBContext, []*datamodel.ProductDataModel) { - sqlLiteGormDB, err := c.createSQLLiteDB() - c.Require().NoError(err) +func (c *UnitTestSharedFixture) setupDB() { + dbContext := c.createSQLLiteDBContext() + c.CatalogDBContext = dbContext - dbContext := dbcontext.NewCatalogsDBContext(sqlLiteGormDB, c.Log) + c.initDB(dbContext) +} - err = migrateGorm(dbContext) +func (c *UnitTestSharedFixture) initDB(dbContext *dbcontext.CatalogsGormDBContext) { + // migrations for our database + err := migrateGorm(dbContext) c.Require().NoError(err) - items, err := seedData(dbContext) + // seed data for our tests + items, err := seedDataManually(dbContext) c.Require().NoError(err) - return dbContext, items + c.Products = items } -func (c *UnitTestSharedFixture) BeginTx() { - c.Log.Info("starting transaction") - tx := c.CatalogDBContext.Begin() - gormContext := helpers.SetTxToContext(c.Ctx, tx) - c.Ctx = gormContext - - var productData []*datamodel.ProductDataModel - var productData2 []*datamodel.ProductDataModel +func (c *UnitTestSharedFixture) cleanupDB() error { + sqldb, _ := c.CatalogDBContext.DB.DB() + e := sqldb.Close() + c.Require().NoError(e) - s := c.CatalogDBContext.Find(&productData).Error - s2 := tx.Find(&productData2).Error - fmt.Println(s) - fmt.Println(s2) -} + // removing sql-lite file + err := os.Remove(c.dbFilePath) -func (c *UnitTestSharedFixture) CommitTx() { - tx := helpers.GetTxFromContextIfExists(c.Ctx) - if tx != nil { - c.Log.Info("committing transaction") - tx.Commit() - } + return err } -func (c *UnitTestSharedFixture) createSQLLiteDB() (*gorm.DB, error) { - dbFilePath := filepath.Join(c.projectRootDir, c.dbFileName) - +func (c *UnitTestSharedFixture) createSQLLiteDBContext() *dbcontext.CatalogsGormDBContext { // https://gorm.io/docs/connecting_to_the_database.html#SQLite // https://github.com/glebarez/sqlite // https://www.connectionstrings.com/sqlite/ - gormDB, err := gorm.Open( - sqlite.Open(dbFilePath), + gormSQLLiteDB, err := gorm.Open( + sqlite.Open(c.dbFilePath), &gorm.Config{ Logger: gromlog.NewGormCustomLogger(defaultLogger.GetLogger()), }) + c.Require().NoError(err) - return gormDB, err -} - -func (c *UnitTestSharedFixture) dropSQLLiteDB() error { - sqldb, _ := c.CatalogDBContext.DB.DB() - e := sqldb.Close() - c.Require().NoError(e) - - dbFilePath := filepath.Join(c.projectRootDir, c.dbFileName) - err := os.Remove(dbFilePath) + dbContext := dbcontext.NewCatalogsDBContext(gormSQLLiteDB, c.Log) - return err + return dbContext } func migrateGorm(dbContext *dbcontext.CatalogsGormDBContext) error { @@ -171,19 +180,19 @@ func migrateGorm(dbContext *dbcontext.CatalogsGormDBContext) error { return nil } -func seedData( +func seedDataManually( dbContext *dbcontext.CatalogsGormDBContext, ) ([]*datamodel.ProductDataModel, error) { products := []*datamodel.ProductDataModel{ { - ProductId: uuid.NewV4(), + Id: uuid.NewV4(), Name: gofakeit.Name(), CreatedAt: time.Now(), Description: gofakeit.AdjectiveDescriptive(), Price: gofakeit.Price(100, 1000), }, { - ProductId: uuid.NewV4(), + Id: uuid.NewV4(), Name: gofakeit.Name(), CreatedAt: time.Now(), Description: gofakeit.AdjectiveDescriptive(), @@ -191,7 +200,6 @@ func seedData( }, } - // migration will do in app configuration // seed data err := dbContext.DB.CreateInBatches(products, len(products)).Error if err != nil { diff --git a/internal/services/catalog_write_service/mocks/CatalogContext.go b/internal/services/catalogwriteservice/mocks/CatalogContext.go similarity index 100% rename from internal/services/catalog_write_service/mocks/CatalogContext.go rename to internal/services/catalogwriteservice/mocks/CatalogContext.go diff --git a/internal/services/catalog_write_service/mocks/ProductRepository.go b/internal/services/catalogwriteservice/mocks/ProductRepository.go similarity index 100% rename from internal/services/catalog_write_service/mocks/ProductRepository.go rename to internal/services/catalogwriteservice/mocks/ProductRepository.go diff --git a/internal/services/catalog_write_service/mocks/ProductsServiceClient.go b/internal/services/catalogwriteservice/mocks/ProductsServiceClient.go similarity index 100% rename from internal/services/catalog_write_service/mocks/ProductsServiceClient.go rename to internal/services/catalogwriteservice/mocks/ProductsServiceClient.go diff --git a/internal/services/catalog_write_service/mocks/ProductsServiceServer.go b/internal/services/catalogwriteservice/mocks/ProductsServiceServer.go similarity index 100% rename from internal/services/catalog_write_service/mocks/ProductsServiceServer.go rename to internal/services/catalogwriteservice/mocks/ProductsServiceServer.go diff --git a/internal/services/catalog_write_service/mocks/UnsafeProductsServiceServer.go b/internal/services/catalogwriteservice/mocks/UnsafeProductsServiceServer.go similarity index 100% rename from internal/services/catalog_write_service/mocks/UnsafeProductsServiceServer.go rename to internal/services/catalogwriteservice/mocks/UnsafeProductsServiceServer.go diff --git a/internal/services/catalog_write_service/readme.md b/internal/services/catalogwriteservice/readme.md similarity index 100% rename from internal/services/catalog_write_service/readme.md rename to internal/services/catalogwriteservice/readme.md diff --git a/internal/services/catalog_write_service/revive-config.toml b/internal/services/catalogwriteservice/revive-config.toml similarity index 100% rename from internal/services/catalog_write_service/revive-config.toml rename to internal/services/catalogwriteservice/revive-config.toml diff --git a/internal/services/catalog_write_service/taskfile.yml b/internal/services/catalogwriteservice/taskfile.yml similarity index 100% rename from internal/services/catalog_write_service/taskfile.yml rename to internal/services/catalogwriteservice/taskfile.yml diff --git a/internal/services/catalog_write_service/taskfile_db.yml b/internal/services/catalogwriteservice/taskfile_db.yml similarity index 100% rename from internal/services/catalog_write_service/taskfile_db.yml rename to internal/services/catalogwriteservice/taskfile_db.yml diff --git a/internal/services/catalog_write_service/taskfile_test.yml b/internal/services/catalogwriteservice/taskfile_test.yml similarity index 100% rename from internal/services/catalog_write_service/taskfile_test.yml rename to internal/services/catalogwriteservice/taskfile_test.yml diff --git a/internal/services/catalog_write_service/test/endtoend/products/features/creatingproduct/v1/create_product_test.go b/internal/services/catalogwriteservice/test/endtoend/products/features/creatingproduct/v1/create_product_test.go similarity index 100% rename from internal/services/catalog_write_service/test/endtoend/products/features/creatingproduct/v1/create_product_test.go rename to internal/services/catalogwriteservice/test/endtoend/products/features/creatingproduct/v1/create_product_test.go diff --git a/internal/services/catalog_write_service/test/endtoend/products/features/deletingproduct/v1/delete_product_test.go b/internal/services/catalogwriteservice/test/endtoend/products/features/deletingproduct/v1/delete_product_test.go similarity index 97% rename from internal/services/catalog_write_service/test/endtoend/products/features/deletingproduct/v1/delete_product_test.go rename to internal/services/catalogwriteservice/test/endtoend/products/features/deletingproduct/v1/delete_product_test.go index 1f9a52c3..42d3f788 100644 --- a/internal/services/catalog_write_service/test/endtoend/products/features/deletingproduct/v1/delete_product_test.go +++ b/internal/services/catalogwriteservice/test/endtoend/products/features/deletingproduct/v1/delete_product_test.go @@ -37,7 +37,7 @@ var _ = Describe("Delete Product Feature", func() { By("Seeding the required data") integrationFixture.SetupTest() - id = integrationFixture.Items[0].ProductId + id = integrationFixture.Items[0].Id }) _ = AfterEach(func() { diff --git a/internal/services/catalog_write_service/test/endtoend/products/features/gettingproductbyid/v1/get_product_by_id_test.go b/internal/services/catalogwriteservice/test/endtoend/products/features/gettingproductbyid/v1/get_product_by_id_test.go similarity index 97% rename from internal/services/catalog_write_service/test/endtoend/products/features/gettingproductbyid/v1/get_product_by_id_test.go rename to internal/services/catalogwriteservice/test/endtoend/products/features/gettingproductbyid/v1/get_product_by_id_test.go index dc035dea..256ca88c 100644 --- a/internal/services/catalog_write_service/test/endtoend/products/features/gettingproductbyid/v1/get_product_by_id_test.go +++ b/internal/services/catalogwriteservice/test/endtoend/products/features/gettingproductbyid/v1/get_product_by_id_test.go @@ -37,7 +37,7 @@ var _ = Describe("Get Product By Id Feature", func() { By("Seeding the required data") integrationFixture.SetupTest() - id = integrationFixture.Items[0].ProductId + id = integrationFixture.Items[0].Id }) _ = AfterEach(func() { diff --git a/internal/services/catalog_write_service/test/endtoend/products/features/gettingproducts/v1/get_products_test.go b/internal/services/catalogwriteservice/test/endtoend/products/features/gettingproducts/v1/get_products_test.go similarity index 100% rename from internal/services/catalog_write_service/test/endtoend/products/features/gettingproducts/v1/get_products_test.go rename to internal/services/catalogwriteservice/test/endtoend/products/features/gettingproducts/v1/get_products_test.go diff --git a/internal/services/catalog_write_service/test/endtoend/products/features/searchingproduct/v1/search_products_test.go b/internal/services/catalogwriteservice/test/endtoend/products/features/searchingproduct/v1/search_products_test.go similarity index 100% rename from internal/services/catalog_write_service/test/endtoend/products/features/searchingproduct/v1/search_products_test.go rename to internal/services/catalogwriteservice/test/endtoend/products/features/searchingproduct/v1/search_products_test.go diff --git a/internal/services/catalog_write_service/test/endtoend/products/features/updatingproduct/v1/update_product_test.go b/internal/services/catalogwriteservice/test/endtoend/products/features/updatingproduct/v1/update_product_test.go similarity index 98% rename from internal/services/catalog_write_service/test/endtoend/products/features/updatingproduct/v1/update_product_test.go rename to internal/services/catalogwriteservice/test/endtoend/products/features/updatingproduct/v1/update_product_test.go index fc66699a..41d46e15 100644 --- a/internal/services/catalog_write_service/test/endtoend/products/features/updatingproduct/v1/update_product_test.go +++ b/internal/services/catalogwriteservice/test/endtoend/products/features/updatingproduct/v1/update_product_test.go @@ -39,7 +39,7 @@ var _ = Describe("UpdateProductE2ETest Suite", func() { By("Seeding the required data") integrationFixture.SetupTest() - id = integrationFixture.Items[0].ProductId + id = integrationFixture.Items[0].Id }) _ = AfterEach(func() { diff --git a/internal/services/catalog_write_service/test/endtoend/products/grpc/product_grpc_service_server_test.go b/internal/services/catalogwriteservice/test/endtoend/products/grpc/product_grpc_service_server_test.go similarity index 93% rename from internal/services/catalog_write_service/test/endtoend/products/grpc/product_grpc_service_server_test.go rename to internal/services/catalogwriteservice/test/endtoend/products/grpc/product_grpc_service_server_test.go index 6bc06f19..0bc9e32f 100644 --- a/internal/services/catalog_write_service/test/endtoend/products/grpc/product_grpc_service_server_test.go +++ b/internal/services/catalogwriteservice/test/endtoend/products/grpc/product_grpc_service_server_test.go @@ -37,7 +37,7 @@ var _ = Describe("Product Grpc Service Feature", func() { By("Seeding the required data") integrationFixture.SetupTest() - id = integrationFixture.Items[0].ProductId + id = integrationFixture.Items[0].Id }) _ = AfterEach(func() { @@ -50,7 +50,7 @@ var _ = Describe("Product Grpc Service Feature", func() { // "When" step When("A request is made to create a product with valid data", func() { // "Then" step - It("Should return a non-empty ProductId", func() { + It("Should return a non-empty Id", func() { // Create a gRPC request with valid data request := &productService.CreateProductReq{ Price: gofakeit.Price(100, 1000), @@ -72,7 +72,7 @@ var _ = Describe("Product Grpc Service Feature", func() { // "When" step When("A request is made to retrieve data with a valid ID", func() { // "Then" step - It("Should return data with a matching ProductId", func() { + It("Should return data with a matching Id", func() { // Make the gRPC request to retrieve data by ID res, err := integrationFixture.ProductServiceClient.GetProductById( ctx, diff --git a/internal/services/catalog_write_service/test/integration/products/data/repositories/pg_product_repository_integration_test.go b/internal/services/catalogwriteservice/test/integration/products/data/repositories/pg_product_repository_integration_test.go similarity index 94% rename from internal/services/catalog_write_service/test/integration/products/data/repositories/pg_product_repository_integration_test.go rename to internal/services/catalogwriteservice/test/integration/products/data/repositories/pg_product_repository_integration_test.go index b8b8fa4b..58d5fc0e 100644 --- a/internal/services/catalog_write_service/test/integration/products/data/repositories/pg_product_repository_integration_test.go +++ b/internal/services/catalogwriteservice/test/integration/products/data/repositories/pg_product_repository_integration_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" @@ -44,7 +44,7 @@ var _ = Describe("Product Repository Suite", func() { By("Seeding the required data") integrationFixture.SetupTest() - id = integrationFixture.Items[0].ProductId + id = integrationFixture.Items[0].Id }) _ = AfterEach(func() { @@ -76,7 +76,7 @@ var _ = Describe("Product Repository Suite", func() { product = &models.Product{ Name: gofakeit.Name(), Description: gofakeit.AdjectiveDescriptive(), - ProductId: uuid.NewV4(), + Id: uuid.NewV4(), Price: gofakeit.Price(100, 1000), CreatedAt: time.Now(), } @@ -97,18 +97,18 @@ var _ = Describe("Product Repository Suite", func() { Expect(createdProduct).NotTo(BeNil()) }) - It("Should have the same ProductId as the input product", func() { - Expect(createdProduct.ProductId).To(Equal(product.ProductId)) + It("Should have the same Id as the input product", func() { + Expect(createdProduct.Id).To(Equal(product.Id)) }) It("Should be able to retrieve the created product from the database", func() { retrievedProduct, err := integrationFixture.ProductRepository.GetProductById( ctx, - createdProduct.ProductId, + createdProduct.Id, ) Expect(err).NotTo(HaveOccurred()) Expect(retrievedProduct).NotTo(BeNil()) - Expect(retrievedProduct.ProductId).To(Equal(createdProduct.ProductId)) + Expect(retrievedProduct.ProductId).To(Equal(createdProduct.Id)) }) }) }) @@ -137,7 +137,7 @@ var _ = Describe("Product Repository Suite", func() { It("Should be able to retrieve the updated product from the database", func() { updatedProduct, err = integrationFixture.ProductRepository.GetProductById( ctx, - existingProduct.ProductId, + existingProduct.Id, ) Expect(err).To(BeNil()) Expect(updatedProduct).NotTo(BeNil()) @@ -196,7 +196,7 @@ var _ = Describe("Product Repository Suite", func() { }) It("should retrieve correct data from database by Id", func() { - Expect(existingProduct.ProductId).To(Equal(id)) + Expect(existingProduct.Id).To(Equal(id)) }) }) }) diff --git a/internal/services/catalog_write_service/test/integration/products/data/uow/catalogs_unit_of_work_integration_test.go b/internal/services/catalogwriteservice/test/integration/products/data/uow/catalogs_unit_of_work_integration_test.go similarity index 97% rename from internal/services/catalog_write_service/test/integration/products/data/uow/catalogs_unit_of_work_integration_test.go rename to internal/services/catalogwriteservice/test/integration/products/data/uow/catalogs_unit_of_work_integration_test.go index d4045033..5853b6a9 100644 --- a/internal/services/catalog_write_service/test/integration/products/data/uow/catalogs_unit_of_work_integration_test.go +++ b/internal/services/catalogwriteservice/test/integration/products/data/uow/catalogs_unit_of_work_integration_test.go @@ -58,7 +58,7 @@ var _ = Describe("CatalogsUnitOfWork Feature", func() { &models.Product{ Name: gofakeit.Name(), Description: gofakeit.AdjectiveDescriptive(), - ProductId: uuid.NewV4(), + Id: uuid.NewV4(), Price: gofakeit.Price(100, 1000), CreatedAt: time.Now(), }) @@ -87,7 +87,7 @@ var _ = Describe("CatalogsUnitOfWork Feature", func() { &models.Product{ Name: gofakeit.Name(), Description: gofakeit.AdjectiveDescriptive(), - ProductId: uuid.NewV4(), + Id: uuid.NewV4(), Price: gofakeit.Price(100, 1000), CreatedAt: time.Now(), }) @@ -119,7 +119,7 @@ var _ = Describe("CatalogsUnitOfWork Feature", func() { &models.Product{ Name: gofakeit.Name(), Description: gofakeit.AdjectiveDescriptive(), - ProductId: uuid.NewV4(), + Id: uuid.NewV4(), Price: gofakeit.Price(100, 1000), CreatedAt: time.Now(), }) @@ -129,7 +129,7 @@ var _ = Describe("CatalogsUnitOfWork Feature", func() { &models.Product{ Name: gofakeit.Name(), Description: gofakeit.AdjectiveDescriptive(), - ProductId: uuid.NewV4(), + Id: uuid.NewV4(), Price: gofakeit.Price(100, 1000), CreatedAt: time.Now(), }) @@ -160,7 +160,7 @@ var _ = Describe("CatalogsUnitOfWork Feature", func() { &models.Product{ Name: gofakeit.Name(), Description: gofakeit.AdjectiveDescriptive(), - ProductId: uuid.NewV4(), + Id: uuid.NewV4(), Price: gofakeit.Price(100, 1000), CreatedAt: time.Now(), }) diff --git a/internal/services/catalog_write_service/test/integration/products/features/creatingproduct/v1/create_product_test.go b/internal/services/catalogwriteservice/test/integration/products/features/creatingproduct/v1/create_product_test.go similarity index 98% rename from internal/services/catalog_write_service/test/integration/products/features/creatingproduct/v1/create_product_test.go rename to internal/services/catalogwriteservice/test/integration/products/features/creatingproduct/v1/create_product_test.go index 88748d75..c561502b 100644 --- a/internal/services/catalog_write_service/test/integration/products/features/creatingproduct/v1/create_product_test.go +++ b/internal/services/catalogwriteservice/test/integration/products/features/creatingproduct/v1/create_product_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/hypothesis" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging" createProductCommand "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1" @@ -52,7 +52,7 @@ var _ = Describe("Creating Product Feature", func() { integrationFixture.SetupTest() // child hook codes should be here - id = integrationFixture.Items[0].ProductId + id = integrationFixture.Items[0].Id }) _ = AfterEach(func() { diff --git a/internal/services/catalog_write_service/test/integration/products/features/deletingproduct/v1/delete_product_test.go b/internal/services/catalogwriteservice/test/integration/products/features/deletingproduct/v1/delete_product_test.go similarity index 98% rename from internal/services/catalog_write_service/test/integration/products/features/deletingproduct/v1/delete_product_test.go rename to internal/services/catalogwriteservice/test/integration/products/features/deletingproduct/v1/delete_product_test.go index 80d20531..759b8a23 100644 --- a/internal/services/catalog_write_service/test/integration/products/features/deletingproduct/v1/delete_product_test.go +++ b/internal/services/catalogwriteservice/test/integration/products/features/deletingproduct/v1/delete_product_test.go @@ -9,7 +9,7 @@ import ( "testing" "time" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/hypothesis" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging" v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1" @@ -50,7 +50,7 @@ var _ = Describe("Delete Product Feature", func() { integrationFixture.SetupTest() // child hook codes should be here - id = integrationFixture.Items[0].ProductId + id = integrationFixture.Items[0].Id }) _ = AfterEach(func() { diff --git a/internal/services/catalog_write_service/test/integration/products/features/gettingproductbyid/v1/get_product_by_id_test.go b/internal/services/catalogwriteservice/test/integration/products/features/gettingproductbyid/v1/get_product_by_id_test.go similarity index 98% rename from internal/services/catalog_write_service/test/integration/products/features/gettingproductbyid/v1/get_product_by_id_test.go rename to internal/services/catalogwriteservice/test/integration/products/features/gettingproductbyid/v1/get_product_by_id_test.go index 1d1cdbca..b92e0ceb 100644 --- a/internal/services/catalog_write_service/test/integration/products/features/gettingproductbyid/v1/get_product_by_id_test.go +++ b/internal/services/catalogwriteservice/test/integration/products/features/gettingproductbyid/v1/get_product_by_id_test.go @@ -9,7 +9,7 @@ import ( "testing" "time" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" getProductByIdQuery "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" @@ -44,7 +44,7 @@ var _ = Describe("Get Product by ID Feature", func() { integrationFixture.SetupTest() // child hook codes should be here - id = integrationFixture.Items[0].ProductId + id = integrationFixture.Items[0].Id }) _ = AfterEach(func() { diff --git a/internal/services/catalog_write_service/test/integration/products/features/gettingproducts/v1/get_products_test.go b/internal/services/catalogwriteservice/test/integration/products/features/gettingproducts/v1/get_products_test.go similarity index 97% rename from internal/services/catalog_write_service/test/integration/products/features/gettingproducts/v1/get_products_test.go rename to internal/services/catalogwriteservice/test/integration/products/features/gettingproducts/v1/get_products_test.go index 34b00d42..c5e2193c 100644 --- a/internal/services/catalog_write_service/test/integration/products/features/gettingproducts/v1/get_products_test.go +++ b/internal/services/catalogwriteservice/test/integration/products/features/gettingproducts/v1/get_products_test.go @@ -9,8 +9,8 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - gettingproductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/dtos" + gettingproductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" "github.com/mehdihadeli/go-mediatr" diff --git a/internal/services/catalog_write_service/test/integration/products/features/updatingproduct/v1/update_product_test.go b/internal/services/catalogwriteservice/test/integration/products/features/updatingproduct/v1/update_product_test.go similarity index 96% rename from internal/services/catalog_write_service/test/integration/products/features/updatingproduct/v1/update_product_test.go rename to internal/services/catalogwriteservice/test/integration/products/features/updatingproduct/v1/update_product_test.go index f97365c2..c3fd60db 100644 --- a/internal/services/catalog_write_service/test/integration/products/features/updatingproduct/v1/update_product_test.go +++ b/internal/services/catalogwriteservice/test/integration/products/features/updatingproduct/v1/update_product_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/hypothesis" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging" datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" @@ -80,7 +80,7 @@ var _ = Describe("Update Product Feature", func() { Context("Given product exists in the database", func() { BeforeEach(func() { command, err = v1.NewUpdateProduct( - existingProduct.ProductId, + existingProduct.Id, "Updated Product Name", existingProduct.Description, existingProduct.Price, @@ -112,13 +112,13 @@ var _ = Describe("Update Product Feature", func() { func() { updatedProduct, err := integrationFixture.CatalogsDBContext.FindProductByID( ctx, - existingProduct.ProductId, + existingProduct.Id, ) Expect(err).To(BeNil()) Expect(updatedProduct).NotTo(BeNil()) Expect( - updatedProduct.ProductId, - ).To(Equal(existingProduct.ProductId)) + updatedProduct.Id, + ).To(Equal(existingProduct.Id)) Expect( updatedProduct.Price, ).To(Equal(existingProduct.Price)) @@ -192,7 +192,7 @@ var _ = Describe("Update Product Feature", func() { Context("Given product exists in the database", func() { BeforeEach(func() { command, err = v1.NewUpdateProduct( - existingProduct.ProductId, + existingProduct.Id, "Updated Product Name", existingProduct.Description, existingProduct.Price, diff --git a/internal/services/catalog_write_service/test/load/.openapi-generator-ignore b/internal/services/catalogwriteservice/test/load/.openapi-generator-ignore similarity index 100% rename from internal/services/catalog_write_service/test/load/.openapi-generator-ignore rename to internal/services/catalogwriteservice/test/load/.openapi-generator-ignore diff --git a/internal/services/catalog_write_service/test/load/.openapi-generator/FILES b/internal/services/catalogwriteservice/test/load/.openapi-generator/FILES similarity index 100% rename from internal/services/catalog_write_service/test/load/.openapi-generator/FILES rename to internal/services/catalogwriteservice/test/load/.openapi-generator/FILES diff --git a/internal/services/catalog_write_service/test/load/.openapi-generator/VERSION b/internal/services/catalogwriteservice/test/load/.openapi-generator/VERSION similarity index 100% rename from internal/services/catalog_write_service/test/load/.openapi-generator/VERSION rename to internal/services/catalogwriteservice/test/load/.openapi-generator/VERSION diff --git a/internal/services/catalog_write_service/test/load/README.md b/internal/services/catalogwriteservice/test/load/README.md similarity index 100% rename from internal/services/catalog_write_service/test/load/README.md rename to internal/services/catalogwriteservice/test/load/README.md diff --git a/internal/services/catalog_write_service/test/load/script.js b/internal/services/catalogwriteservice/test/load/script.js similarity index 100% rename from internal/services/catalog_write_service/test/load/script.js rename to internal/services/catalogwriteservice/test/load/script.js diff --git a/internal/services/catalog_write_service/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go b/internal/services/catalogwriteservice/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go similarity index 98% rename from internal/services/catalog_write_service/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go rename to internal/services/catalogwriteservice/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go index a2cd30f6..af38d30e 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go +++ b/internal/services/catalogwriteservice/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go @@ -8,7 +8,7 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" creatingproductv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1" @@ -74,7 +74,7 @@ func (c *createProductHandlerUnitTests) Test_Handle_Should_Create_New_Product_Wi res, err := c.CatalogDBContext.FindProductByID(c.Ctx, id) c.Require().NoError(err) - c.Assert().Equal(res.ProductId, id) + c.Assert().Equal(res.Id, id) } func (c *createProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Duplicate_Item() { diff --git a/internal/services/catalog_write_service/test/unit/products/features/creatingproduct/v1/create_product_unit_test.go b/internal/services/catalogwriteservice/test/unit/products/features/creatingproduct/v1/create_product_unit_test.go similarity index 100% rename from internal/services/catalog_write_service/test/unit/products/features/creatingproduct/v1/create_product_unit_test.go rename to internal/services/catalogwriteservice/test/unit/products/features/creatingproduct/v1/create_product_unit_test.go diff --git a/internal/services/catalog_write_service/test/unit/products/features/deletingproduct/v1/delete_product_handler_unit_test.go b/internal/services/catalogwriteservice/test/unit/products/features/deletingproduct/v1/delete_product_handler_unit_test.go similarity index 96% rename from internal/services/catalog_write_service/test/unit/products/features/deletingproduct/v1/delete_product_handler_unit_test.go rename to internal/services/catalogwriteservice/test/unit/products/features/deletingproduct/v1/delete_product_handler_unit_test.go index 7a551929..ad12a250 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/deletingproduct/v1/delete_product_handler_unit_test.go +++ b/internal/services/catalogwriteservice/test/unit/products/features/deletingproduct/v1/delete_product_handler_unit_test.go @@ -8,7 +8,7 @@ import ( "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" deletingproductv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" @@ -53,7 +53,7 @@ func (c *deleteProductHandlerUnitTests) TearDownTest() { } func (c *deleteProductHandlerUnitTests) Test_Handle_Should_Delete_Product_With_Valid_Id() { - id := c.Products[0].ProductId + id := c.Products[0].Id deleteProduct := &deletingproductv1.DeleteProduct{ ProductID: id, @@ -92,7 +92,7 @@ func (c *deleteProductHandlerUnitTests) Test_Handle_Should_Return_NotFound_Error } func (c *deleteProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Error_In_Bus() { - id := c.Products[0].ProductId + id := c.Products[0].Id deleteProduct := &deletingproductv1.DeleteProduct{ ProductID: id, diff --git a/internal/services/catalog_write_service/test/unit/products/features/deletingproduct/v1/delete_product_unit_test.go b/internal/services/catalogwriteservice/test/unit/products/features/deletingproduct/v1/delete_product_unit_test.go similarity index 100% rename from internal/services/catalog_write_service/test/unit/products/features/deletingproduct/v1/delete_product_unit_test.go rename to internal/services/catalogwriteservice/test/unit/products/features/deletingproduct/v1/delete_product_unit_test.go diff --git a/internal/services/catalog_write_service/test/unit/products/features/gettingproductbyid/v1/get_product_by_Id_unit_test.go b/internal/services/catalogwriteservice/test/unit/products/features/gettingproductbyid/v1/get_product_by_Id_unit_test.go similarity index 100% rename from internal/services/catalog_write_service/test/unit/products/features/gettingproductbyid/v1/get_product_by_Id_unit_test.go rename to internal/services/catalogwriteservice/test/unit/products/features/gettingproductbyid/v1/get_product_by_Id_unit_test.go diff --git a/internal/services/catalog_write_service/test/unit/products/features/gettingproductbyid/v1/get_product_by_id_handler_unit_test.go b/internal/services/catalogwriteservice/test/unit/products/features/gettingproductbyid/v1/get_product_by_id_handler_unit_test.go similarity index 92% rename from internal/services/catalog_write_service/test/unit/products/features/gettingproductbyid/v1/get_product_by_id_handler_unit_test.go rename to internal/services/catalogwriteservice/test/unit/products/features/gettingproductbyid/v1/get_product_by_id_handler_unit_test.go index 7daf7d12..24912f25 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/gettingproductbyid/v1/get_product_by_id_handler_unit_test.go +++ b/internal/services/catalogwriteservice/test/unit/products/features/gettingproductbyid/v1/get_product_by_id_handler_unit_test.go @@ -8,7 +8,7 @@ import ( "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" gettingproductbyidv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1" @@ -50,14 +50,14 @@ func (c *getProductByIdHandlerTest) TearDownTest() { func (c *getProductByIdHandlerTest) Test_Handle_Should_Return_Correct_Product_By_ID() { product := c.Products[0] - query, err := gettingproductbyidv1.NewGetProductById(product.ProductId) + query, err := gettingproductbyidv1.NewGetProductById(product.Id) c.Require().NoError(err) dto, err := c.handler.Handle(c.Ctx, query) c.Require().NoError(err) c.Assert().NotNil(dto) c.Assert().NotNil(dto.Product) - c.Assert().Equal(dto.Product.ProductId, product.ProductId) + c.Assert().Equal(dto.Product.ProductId, product.Id) c.Assert().Equal(dto.Product.Name, product.Name) } @@ -85,7 +85,7 @@ func (c *getProductByIdHandlerTest) Test_Handle_Should_Return_Error_For_Error_In product := c.Products[0] - query, err := gettingproductbyidv1.NewGetProductById(product.ProductId) + query, err := gettingproductbyidv1.NewGetProductById(product.Id) c.Require().NoError(err) dto, err := c.handler.Handle(c.Ctx, query) diff --git a/internal/services/catalog_write_service/test/unit/products/features/gettingproducts/v1/get_products_handler_unit_test.go b/internal/services/catalogwriteservice/test/unit/products/features/gettingproducts/v1/get_products_handler_unit_test.go similarity index 94% rename from internal/services/catalog_write_service/test/unit/products/features/gettingproducts/v1/get_products_handler_unit_test.go rename to internal/services/catalogwriteservice/test/unit/products/features/gettingproducts/v1/get_products_handler_unit_test.go index 74a3b12a..4efc434e 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/gettingproducts/v1/get_products_handler_unit_test.go +++ b/internal/services/catalogwriteservice/test/unit/products/features/gettingproducts/v1/get_products_handler_unit_test.go @@ -8,12 +8,12 @@ import ( "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" - gettingproductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/getting_products/v1/dtos" + gettingproductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/dtos" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" "github.com/stretchr/testify/suite" diff --git a/internal/services/catalog_write_service/test/unit/products/features/searchingproducts/v1/search_products_unit_test.go b/internal/services/catalogwriteservice/test/unit/products/features/searchingproducts/v1/search_products_unit_test.go similarity index 98% rename from internal/services/catalog_write_service/test/unit/products/features/searchingproducts/v1/search_products_unit_test.go rename to internal/services/catalogwriteservice/test/unit/products/features/searchingproducts/v1/search_products_unit_test.go index 7f199cc5..ea5db3ea 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/searchingproducts/v1/search_products_unit_test.go +++ b/internal/services/catalogwriteservice/test/unit/products/features/searchingproducts/v1/search_products_unit_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" diff --git a/internal/services/catalog_write_service/test/unit/products/features/updatingproduct/v1/update_product_handler_unit_test.go b/internal/services/catalogwriteservice/test/unit/products/features/updatingproduct/v1/update_product_handler_unit_test.go similarity index 92% rename from internal/services/catalog_write_service/test/unit/products/features/updatingproduct/v1/update_product_handler_unit_test.go rename to internal/services/catalogwriteservice/test/unit/products/features/updatingproduct/v1/update_product_handler_unit_test.go index efd27042..961fd945 100644 --- a/internal/services/catalog_write_service/test/unit/products/features/updatingproduct/v1/update_product_handler_unit_test.go +++ b/internal/services/catalogwriteservice/test/unit/products/features/updatingproduct/v1/update_product_handler_unit_test.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" updatingoroductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" @@ -37,7 +37,7 @@ func TestUpdateProductHandlerUnit(t *testing.T) { } func (c *updateProductHandlerUnitTests) SetupTest() { - // call base SetupTest hook before running child hook + // call base `SetupTest hook` before running child hook c.UnitTestSharedFixture.SetupTest() c.handler = updatingoroductsv1.NewUpdateProductHandler( fxparams.ProductHandlerParams{ @@ -50,7 +50,7 @@ func (c *updateProductHandlerUnitTests) SetupTest() { } func (c *updateProductHandlerUnitTests) TearDownTest() { - // call base TearDownTest hook before running child hook + // call base `TearDownTest hook` before running child hook c.UnitTestSharedFixture.TearDownTest() } @@ -58,7 +58,7 @@ func (c *updateProductHandlerUnitTests) Test_Handle_Should_Update_Product_With_V existing := c.Products[0] updateProductCommand, err := updatingoroductsv1.NewUpdateProduct( - existing.ProductId, + existing.Id, gofakeit.Name(), gofakeit.EmojiDescription(), existing.Price, @@ -77,7 +77,7 @@ func (c *updateProductHandlerUnitTests) Test_Handle_Should_Update_Product_With_V ) c.Require().NoError(err) - c.Assert().Equal(updatedProduct.ProductId, updateProductCommand.ProductID) + c.Assert().Equal(updatedProduct.Id, updateProductCommand.ProductID) c.Assert().Equal(updatedProduct.Name, updateProductCommand.Name) c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 1) } @@ -109,7 +109,7 @@ func (c *updateProductHandlerUnitTests) Test_Handle_Should_Return_Error_For_Erro existing := c.Products[0] updateProductCommand, err := updatingoroductsv1.NewUpdateProduct( - existing.ProductId, + existing.Id, gofakeit.Name(), gofakeit.EmojiDescription(), existing.Price, diff --git a/internal/services/catalog_write_service/test/unit/products/features/updatingproduct/v1/update_product_unit_test.go b/internal/services/catalogwriteservice/test/unit/products/features/updatingproduct/v1/update_product_unit_test.go similarity index 100% rename from internal/services/catalog_write_service/test/unit/products/features/updatingproduct/v1/update_product_unit_test.go rename to internal/services/catalogwriteservice/test/unit/products/features/updatingproduct/v1/update_product_unit_test.go diff --git a/internal/services/catalog_write_service/test/unit/products/mappings_profile_test.go b/internal/services/catalogwriteservice/test/unit/products/mappings_profile_test.go similarity index 94% rename from internal/services/catalog_write_service/test/unit/products/mappings_profile_test.go rename to internal/services/catalogwriteservice/test/unit/products/mappings_profile_test.go index 38a45fbd..f675268b 100644 --- a/internal/services/catalog_write_service/test/unit/products/mappings_profile_test.go +++ b/internal/services/catalogwriteservice/test/unit/products/mappings_profile_test.go @@ -30,7 +30,7 @@ func TestMappingProfileUnit(t *testing.T) { func (m *mappingProfileUnitTests) Test_Mappings() { productModel := &models.Product{ - ProductId: uuid.NewV4(), + Id: uuid.NewV4(), Name: gofakeit.Name(), CreatedAt: time.Now(), Description: gofakeit.EmojiDescription(), @@ -48,7 +48,7 @@ func (m *mappingProfileUnitTests) Test_Mappings() { m.Run("Should_Map_Product_To_ProductDto", func() { d, err := mapper.Map[*dtoV1.ProductDto](productModel) m.Require().NoError(err) - m.Equal(productModel.ProductId, d.ProductId) + m.Equal(productModel.Id, d.ProductId) m.Equal(productModel.Name, d.Name) }) @@ -61,7 +61,7 @@ func (m *mappingProfileUnitTests) Test_Mappings() { m.Run("Should_Map_ProductDto_To_Product", func() { d, err := mapper.Map[*models.Product](productDto) m.Require().NoError(err) - m.Equal(productDto.ProductId, d.ProductId) + m.Equal(productDto.ProductId, d.Id) m.Equal(productDto.Name, d.Name) }) diff --git a/internal/services/order_service/.env b/internal/services/order_service/.env deleted file mode 100644 index d883e79f..00000000 --- a/internal/services/order_service/.env +++ /dev/null @@ -1 +0,0 @@ -PROJECT_NAME=order_service diff --git a/internal/services/order_service/.air.toml b/internal/services/orderservice/.air.toml similarity index 100% rename from internal/services/order_service/.air.toml rename to internal/services/orderservice/.air.toml diff --git a/internal/services/order_service/.dockerignore b/internal/services/orderservice/.dockerignore similarity index 100% rename from internal/services/order_service/.dockerignore rename to internal/services/orderservice/.dockerignore diff --git a/internal/services/orderservice/.env b/internal/services/orderservice/.env new file mode 100644 index 00000000..0cedb4bf --- /dev/null +++ b/internal/services/orderservice/.env @@ -0,0 +1 @@ +PROJECT_NAME=orderservice diff --git a/internal/services/order_service/.golangci.yml b/internal/services/orderservice/.golangci.yml similarity index 100% rename from internal/services/order_service/.golangci.yml rename to internal/services/orderservice/.golangci.yml diff --git a/internal/services/order_service/Dockerfile b/internal/services/orderservice/Dockerfile similarity index 100% rename from internal/services/order_service/Dockerfile rename to internal/services/orderservice/Dockerfile diff --git a/internal/services/order_service/Makefile b/internal/services/orderservice/Makefile similarity index 100% rename from internal/services/order_service/Makefile rename to internal/services/orderservice/Makefile diff --git a/internal/services/order_service/arch-go.yml b/internal/services/orderservice/arch-go.yml similarity index 100% rename from internal/services/order_service/arch-go.yml rename to internal/services/orderservice/arch-go.yml diff --git a/internal/services/order_service/client.http b/internal/services/orderservice/client.http similarity index 100% rename from internal/services/order_service/client.http rename to internal/services/orderservice/client.http diff --git a/internal/services/order_service/cmd/app/main.go b/internal/services/orderservice/cmd/app/main.go similarity index 100% rename from internal/services/order_service/cmd/app/main.go rename to internal/services/orderservice/cmd/app/main.go diff --git a/internal/services/order_service/cmd/migration/.gitkeep b/internal/services/orderservice/cmd/migration/.gitkeep similarity index 100% rename from internal/services/order_service/cmd/migration/.gitkeep rename to internal/services/orderservice/cmd/migration/.gitkeep diff --git a/internal/services/order_service/config/config.development.json b/internal/services/orderservice/config/config.development.json similarity index 95% rename from internal/services/order_service/config/config.development.json rename to internal/services/orderservice/config/config.development.json index 059bf573..6e8c1275 100644 --- a/internal/services/order_service/config/config.development.json +++ b/internal/services/orderservice/config/config.development.json @@ -1,16 +1,16 @@ { "appOptions": { - "serviceName": "order_service", + "serviceName": "orderservice", "deliveryType": "http" }, "grpcOptions": { - "name": "order_service", + "name": "orderservice", "port": ":6005", "host": "localhost", "development": true }, "echoHttpOptions": { - "name": "order_service", + "name": "orderservice", "port": ":8000", "development": true, "timeout": 30, diff --git a/internal/services/order_service/config/config.go b/internal/services/orderservice/config/config.go similarity index 100% rename from internal/services/order_service/config/config.go rename to internal/services/orderservice/config/config.go diff --git a/internal/services/order_service/config/config.test.json b/internal/services/orderservice/config/config.test.json similarity index 95% rename from internal/services/order_service/config/config.test.json rename to internal/services/orderservice/config/config.test.json index c9f14c9c..a416ed3a 100644 --- a/internal/services/order_service/config/config.test.json +++ b/internal/services/orderservice/config/config.test.json @@ -1,16 +1,16 @@ { "appOptions": { - "serviceName": "order_service", + "serviceName": "orderservice", "deliveryType": "http" }, "grpcOptions": { - "name": "order_service", + "name": "orderservice", "port": ":3302", "host": "localhost", "development": true }, "echoHttpOptions": { - "name": "order_service", + "name": "orderservice", "port": ":6002", "development": true, "timeout": 30, diff --git a/internal/services/order_service/config/config_fx.go b/internal/services/orderservice/config/config_fx.go similarity index 100% rename from internal/services/order_service/config/config_fx.go rename to internal/services/orderservice/config/config_fx.go diff --git a/internal/services/order_service/docs/docs.go b/internal/services/orderservice/docs/docs.go similarity index 100% rename from internal/services/order_service/docs/docs.go rename to internal/services/orderservice/docs/docs.go diff --git a/internal/services/order_service/docs/swagger.json b/internal/services/orderservice/docs/swagger.json similarity index 100% rename from internal/services/order_service/docs/swagger.json rename to internal/services/orderservice/docs/swagger.json diff --git a/internal/services/order_service/docs/swagger.yaml b/internal/services/orderservice/docs/swagger.yaml similarity index 100% rename from internal/services/order_service/docs/swagger.yaml rename to internal/services/orderservice/docs/swagger.yaml diff --git a/internal/services/order_service/go.mod b/internal/services/orderservice/go.mod similarity index 95% rename from internal/services/order_service/go.mod rename to internal/services/orderservice/go.mod index ceb5850d..21e775e4 100644 --- a/internal/services/order_service/go.mod +++ b/internal/services/orderservice/go.mod @@ -8,7 +8,7 @@ replace github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg => ../../ require ( emperror.dev/errors v0.8.1 github.com/EventStore/EventStore-Client-Go v1.0.2 - github.com/brianvoe/gofakeit/v6 v6.23.2 + github.com/brianvoe/gofakeit/v6 v6.25.0 github.com/elastic/go-elasticsearch/v8 v8.10.0 github.com/gavv/httpexpect/v2 v2.15.0 github.com/go-ozzo/ozzo-validation v3.6.0+incompatible @@ -66,11 +66,14 @@ require ( github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/doug-martin/goqu/v9 v9.18.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/elastic/elastic-transport-go/v8 v8.3.0 // indirect github.com/fatih/color v1.15.0 // indirect github.com/fatih/structs v1.1.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect + github.com/glebarez/go-sqlite v1.21.2 // indirect + github.com/glebarez/sqlite v1.10.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect @@ -154,6 +157,7 @@ require ( github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 // indirect github.com/redis/go-redis/v9 v9.2.1 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/samber/lo v1.38.1 // indirect github.com/sanity-io/litter v1.5.5 // indirect @@ -173,13 +177,14 @@ require ( github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect + github.com/ulule/limiter/v3 v3.11.2 // indirect github.com/uptrace/bun v1.1.16 // indirect github.com/uptrace/bun/driver/pgdriver v1.1.16 // indirect github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.3 // indirect github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.3 // indirect github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.34.0 // indirect + github.com/valyala/fasthttp v1.47.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect github.com/vmihailenco/msgpack/v5 v5.4.0 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect @@ -230,8 +235,12 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gorm.io/driver/postgres v1.5.2 // indirect - gorm.io/gorm v1.25.4 // indirect + gorm.io/gorm v1.25.5 // indirect gorm.io/plugin/opentelemetry v0.1.4 // indirect mellium.im/sasl v0.3.1 // indirect + modernc.org/libc v1.24.1 // indirect + modernc.org/mathutil v1.6.0 // indirect + modernc.org/memory v1.6.0 // indirect + modernc.org/sqlite v1.25.0 // indirect moul.io/http2curl/v2 v2.3.0 // indirect ) diff --git a/internal/services/order_service/go.sum b/internal/services/orderservice/go.sum similarity index 98% rename from internal/services/order_service/go.sum rename to internal/services/orderservice/go.sum index d849c313..909258ac 100644 --- a/internal/services/order_service/go.sum +++ b/internal/services/orderservice/go.sum @@ -93,7 +93,6 @@ github.com/ahmetb/go-linq/v3 v3.2.0 h1:BEuMfp+b59io8g5wYzNoFe9pWPalRklhlhbiU3hYZ github.com/ahmetb/go-linq/v3 v3.2.0/go.mod h1:haQ3JfOeWK8HpVxMtHHEMPVgBKiYyQ+f1/kLZh/cj9U= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA= @@ -108,8 +107,8 @@ github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/brianvoe/gofakeit/v6 v6.23.2 h1:lVde18uhad5wII/f5RMVFLtdQNE0HaGFuBUXmYKk8i8= -github.com/brianvoe/gofakeit/v6 v6.23.2/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8= +github.com/brianvoe/gofakeit/v6 v6.25.0 h1:ZpFjktOpLZUeF8q223o0rUuXtA+m5qW5srjvVi+JkXk= +github.com/brianvoe/gofakeit/v6 v6.25.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= @@ -179,6 +178,8 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/doug-martin/goqu/v9 v9.18.0 h1:/6bcuEtAe6nsSMVK/M+fOiXUNfyFF3yYtE07DBPFMYY= github.com/doug-martin/goqu/v9 v9.18.0/go.mod h1:nf0Wc2/hV3gYK9LiyqIrzBEVGlI8qW3GuDCEobC4wBQ= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/elastic/elastic-transport-go/v8 v8.0.0-20230329154755-1a3c63de0db6/go.mod h1:87Tcz8IVNe6rVSLdBux1o/PEItLtyabHU3naC7IoqKI= github.com/elastic/elastic-transport-go/v8 v8.3.0 h1:DJGxovyQLXGr62e9nDMPSxRyWION0Bh6d9eCFBriiHo= github.com/elastic/elastic-transport-go/v8 v8.3.0/go.mod h1:87Tcz8IVNe6rVSLdBux1o/PEItLtyabHU3naC7IoqKI= @@ -207,6 +208,10 @@ github.com/gavv/httpexpect/v2 v2.15.0 h1:CCnFk9of4l4ijUhnMxyoEpJsIIBKcuWIFLMwwGT github.com/gavv/httpexpect/v2 v2.15.0/go.mod h1:7myOP3A3VyS4+qnA4cm8DAad8zMN+7zxDB80W9f8yIc= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= +github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= +github.com/glebarez/sqlite v1.10.0 h1:u4gt8y7OND/cCei/NMHmfbLxF6xP2wgKcT/BJf2pYkc= +github.com/glebarez/sqlite v1.10.0/go.mod h1:IJ+lfSOmiekhQsFTJRx/lHtGYmCdtAiTaf5wI9u5uHA= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -443,7 +448,6 @@ github.com/kamva/mgm/v3 v3.5.0/go.mod h1:F4J1hZnXQMkqL3DZgR7Z7BOuiTqQG/JTic3Yzli github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -517,10 +521,6 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mcuadros/go-defaults v1.2.0 h1:FODb8WSf0uGaY8elWJAkoLL0Ri6AlZ1bFlenk56oZtc= github.com/mcuadros/go-defaults v1.2.0/go.mod h1:WEZtHEVIGYVDqkKSWBdWKUVdRyKlMfulPaGDWIVeCWY= -github.com/mehdihadeli/go-mediatr v1.1.10 h1:NAzg4065c90lgYeb+Vzbd2WKH0tUFpxzL0mpx6hkU/A= -github.com/mehdihadeli/go-mediatr v1.1.10/go.mod h1:lwgZl7qVL/RKomObBblhG3uEte/r4nJDV95Vd+nGrMw= -github.com/mehdihadeli/go-mediatr v1.2.0 h1:XkzYF/uGfW4pwPWYAxKyY+mO6l989PbmCQWSYHuCZtU= -github.com/mehdihadeli/go-mediatr v1.2.0/go.mod h1:I9LuExxAKz6cTDJyP/SSDSmkHaPHK1/usnvEXjUY47k= github.com/mehdihadeli/go-mediatr v1.3.0 h1:hrb5Scp/nsiR3Y62mjZ0Tc5UX/dRJl4nDFkINBEIESA= github.com/mehdihadeli/go-mediatr v1.3.0/go.mod h1:lsG+hyH+pEOhmZiZl0KPO72BcZiEReF03CBk4GVJB0k= github.com/michaelklishin/rabbit-hole v1.5.0 h1:Bex27BiFDsijCM9D0ezSHqyy0kehpYHuNKaPqq/a4RM= @@ -620,6 +620,8 @@ github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnA github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= @@ -716,6 +718,8 @@ github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+F github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= +github.com/ulule/limiter/v3 v3.11.2 h1:P4yOrxoEMJbOTfRJR2OzjL90oflzYPPmWg+dvwN2tHA= +github.com/ulule/limiter/v3 v3.11.2/go.mod h1:QG5GnFOCV+k7lrL5Y8kgEeeflPH3+Cviqlqa8SVSQxI= github.com/uptrace/bun v1.1.16 h1:cn9cgEMFwcyYRsQLfxCRMUxyK1WaHwOVrR3TvzEFZ/A= github.com/uptrace/bun v1.1.16/go.mod h1:7HnsMRRvpLFUcquJxp22JO8PsWKpFQO/gNXqqsuGWg8= github.com/uptrace/bun/driver/pgdriver v1.1.16 h1:b/NiSXk6Ldw7KLfMLbOqIkm4odHd7QiNOCPLqPFJjK4= @@ -729,12 +733,11 @@ github.com/uptrace/opentelemetry-go-extra/otelzap v0.2.3/go.mod h1:9IVEh9mPv3NwF github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.34.0 h1:d3AAQJ2DRcxJYHm7OXNXtXt2as1vMDfxeIcFvhmGGm4= -github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0= +github.com/valyala/fasthttp v1.47.0 h1:y7moDoxYzMooFpT5aHgNgVOQDrS3qlkfiP9mDtGGK9c= +github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vmihailenco/msgpack/v5 v5.4.0 h1:hRM0digJwyR6vll33NNAwCFguy5JuBD6jxDmQP3l608= @@ -868,7 +871,6 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= @@ -951,7 +953,6 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= @@ -1045,8 +1046,6 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1295,8 +1294,8 @@ gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0= gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8= gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c= gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I= -gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= -gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= +gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/plugin/opentelemetry v0.1.4 h1:7p0ocWELjSSRI7NCKPW2mVe6h43YPini99sNJcbsTuc= gorm.io/plugin/opentelemetry v0.1.4/go.mod h1:tndJHOdvPT0pyGhOb8E2209eXJCUxhC5UpKw7bGVWeI= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= @@ -1311,6 +1310,14 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= mellium.im/sasl v0.3.1 h1:wE0LW6g7U83vhvxjC1IY8DnXM+EU095yeo8XClvCdfo= mellium.im/sasl v0.3.1/go.mod h1:xm59PUYpZHhgQ9ZqoJ5QaCqzWMi8IeS49dhp6plPCzw= +modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM= +modernc.org/libc v1.24.1/go.mod h1:FmfO1RLrU3MHJfyi9eYYmZBfi/R+tqZ6+hQ3yQQUkak= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.6.0 h1:i6mzavxrE9a30whzMfwf7XWVODx2r5OYXvU46cirX7o= +modernc.org/memory v1.6.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/sqlite v1.25.0 h1:AFweiwPNd/b3BoKnBOfFm+Y260guGMF+0UFk0savqeA= +modernc.org/sqlite v1.25.0/go.mod h1:FL3pVXie73rg3Rii6V/u5BoHlSoyeZeIgKZEgHARyCU= moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/internal/services/order_service/internal/orders/configurations/mappings/mappings_profile.go b/internal/services/orderservice/internal/orders/configurations/mappings/mappings_profile.go similarity index 100% rename from internal/services/order_service/internal/orders/configurations/mappings/mappings_profile.go rename to internal/services/orderservice/internal/orders/configurations/mappings/mappings_profile.go diff --git a/internal/services/order_service/internal/orders/configurations/mediatr/mediator_configurations.go b/internal/services/orderservice/internal/orders/configurations/mediatr/mediator_configurations.go similarity index 100% rename from internal/services/order_service/internal/orders/configurations/mediatr/mediator_configurations.go rename to internal/services/orderservice/internal/orders/configurations/mediatr/mediator_configurations.go diff --git a/internal/services/order_service/internal/orders/configurations/orders_module_configurator.go b/internal/services/orderservice/internal/orders/configurations/orders_module_configurator.go similarity index 99% rename from internal/services/order_service/internal/orders/configurations/orders_module_configurator.go rename to internal/services/orderservice/internal/orders/configurations/orders_module_configurator.go index 53470b32..b5ccc37d 100644 --- a/internal/services/order_service/internal/orders/configurations/orders_module_configurator.go +++ b/internal/services/orderservice/internal/orders/configurations/orders_module_configurator.go @@ -5,7 +5,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/contracts/store" contracts2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" grpcServer "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc" - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/configurations/mappings" diff --git a/internal/services/order_service/internal/orders/configurations/rabbitmq/rabbitmq_configurations.go b/internal/services/orderservice/internal/orders/configurations/rabbitmq/rabbitmq_configurations.go similarity index 100% rename from internal/services/order_service/internal/orders/configurations/rabbitmq/rabbitmq_configurations.go rename to internal/services/orderservice/internal/orders/configurations/rabbitmq/rabbitmq_configurations.go diff --git a/internal/services/order_service/internal/orders/contracts/params/order_projection_params.go b/internal/services/orderservice/internal/orders/contracts/params/order_projection_params.go similarity index 100% rename from internal/services/order_service/internal/orders/contracts/params/order_projection_params.go rename to internal/services/orderservice/internal/orders/contracts/params/order_projection_params.go diff --git a/internal/services/order_service/internal/orders/contracts/params/order_route_params.go b/internal/services/orderservice/internal/orders/contracts/params/order_route_params.go similarity index 100% rename from internal/services/order_service/internal/orders/contracts/params/order_route_params.go rename to internal/services/orderservice/internal/orders/contracts/params/order_route_params.go diff --git a/internal/services/order_service/internal/orders/contracts/repositories/order_repository.go b/internal/services/orderservice/internal/orders/contracts/repositories/order_repository.go similarity index 100% rename from internal/services/order_service/internal/orders/contracts/repositories/order_repository.go rename to internal/services/orderservice/internal/orders/contracts/repositories/order_repository.go diff --git a/internal/services/order_service/internal/orders/data/repositories/elastic_order_read_repository.go b/internal/services/orderservice/internal/orders/data/repositories/elastic_order_read_repository.go similarity index 100% rename from internal/services/order_service/internal/orders/data/repositories/elastic_order_read_repository.go rename to internal/services/orderservice/internal/orders/data/repositories/elastic_order_read_repository.go diff --git a/internal/services/order_service/internal/orders/data/repositories/mongo_order_read_repository.go b/internal/services/orderservice/internal/orders/data/repositories/mongo_order_read_repository.go similarity index 100% rename from internal/services/order_service/internal/orders/data/repositories/mongo_order_read_repository.go rename to internal/services/orderservice/internal/orders/data/repositories/mongo_order_read_repository.go diff --git a/internal/services/order_service/internal/orders/dtos/v1/order_dto.go b/internal/services/orderservice/internal/orders/dtos/v1/order_dto.go similarity index 100% rename from internal/services/order_service/internal/orders/dtos/v1/order_dto.go rename to internal/services/orderservice/internal/orders/dtos/v1/order_dto.go diff --git a/internal/services/order_service/internal/orders/dtos/v1/order_read_dto.go b/internal/services/orderservice/internal/orders/dtos/v1/order_read_dto.go similarity index 100% rename from internal/services/order_service/internal/orders/dtos/v1/order_read_dto.go rename to internal/services/orderservice/internal/orders/dtos/v1/order_read_dto.go diff --git a/internal/services/order_service/internal/orders/dtos/v1/shopItem_dto.go b/internal/services/orderservice/internal/orders/dtos/v1/shopItem_dto.go similarity index 100% rename from internal/services/order_service/internal/orders/dtos/v1/shopItem_dto.go rename to internal/services/orderservice/internal/orders/dtos/v1/shopItem_dto.go diff --git a/internal/services/order_service/internal/orders/dtos/v1/shopItem_read_dto.go b/internal/services/orderservice/internal/orders/dtos/v1/shopItem_read_dto.go similarity index 100% rename from internal/services/order_service/internal/orders/dtos/v1/shopItem_read_dto.go rename to internal/services/orderservice/internal/orders/dtos/v1/shopItem_read_dto.go diff --git a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/invalid_delivery_address_error.go b/internal/services/orderservice/internal/orders/exceptions/domain_exceptions/invalid_delivery_address_error.go similarity index 94% rename from internal/services/order_service/internal/orders/exceptions/domain_exceptions/invalid_delivery_address_error.go rename to internal/services/orderservice/internal/orders/exceptions/domain_exceptions/invalid_delivery_address_error.go index 5ebc0d1a..a420de8f 100644 --- a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/invalid_delivery_address_error.go +++ b/internal/services/orderservice/internal/orders/exceptions/domain_exceptions/invalid_delivery_address_error.go @@ -1,7 +1,7 @@ package domainExceptions import ( - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "emperror.dev/errors" ) diff --git a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/invalid_email_error.go b/internal/services/orderservice/internal/orders/exceptions/domain_exceptions/invalid_email_error.go similarity index 94% rename from internal/services/order_service/internal/orders/exceptions/domain_exceptions/invalid_email_error.go rename to internal/services/orderservice/internal/orders/exceptions/domain_exceptions/invalid_email_error.go index e025a2f0..b5a30ec2 100644 --- a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/invalid_email_error.go +++ b/internal/services/orderservice/internal/orders/exceptions/domain_exceptions/invalid_email_error.go @@ -1,7 +1,7 @@ package domainExceptions import ( - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "emperror.dev/errors" ) diff --git a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_domain_errors_test.go b/internal/services/orderservice/internal/orders/exceptions/domain_exceptions/order_domain_errors_test.go similarity index 95% rename from internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_domain_errors_test.go rename to internal/services/orderservice/internal/orders/exceptions/domain_exceptions/order_domain_errors_test.go index 44735cf8..fc06c48b 100644 --- a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_domain_errors_test.go +++ b/internal/services/orderservice/internal/orders/exceptions/domain_exceptions/order_domain_errors_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" - errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/error_utils" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" + errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/errorutils" "github.com/stretchr/testify/assert" ) diff --git a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_items_required_errors.go b/internal/services/orderservice/internal/orders/exceptions/domain_exceptions/order_items_required_errors.go similarity index 94% rename from internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_items_required_errors.go rename to internal/services/orderservice/internal/orders/exceptions/domain_exceptions/order_items_required_errors.go index 61e2647c..ddbc4413 100644 --- a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_items_required_errors.go +++ b/internal/services/orderservice/internal/orders/exceptions/domain_exceptions/order_items_required_errors.go @@ -1,7 +1,7 @@ package domainExceptions import ( - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "emperror.dev/errors" ) diff --git a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_not_found_error.go b/internal/services/orderservice/internal/orders/exceptions/domain_exceptions/order_not_found_error.go similarity index 94% rename from internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_not_found_error.go rename to internal/services/orderservice/internal/orders/exceptions/domain_exceptions/order_not_found_error.go index e1993a07..b9d77100 100644 --- a/internal/services/order_service/internal/orders/exceptions/domain_exceptions/order_not_found_error.go +++ b/internal/services/orderservice/internal/orders/exceptions/domain_exceptions/order_not_found_error.go @@ -3,7 +3,7 @@ package domainExceptions import ( "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "emperror.dev/errors" ) diff --git a/internal/services/order_service/internal/orders/features/creating_order/v1/commands/create_order.go b/internal/services/orderservice/internal/orders/features/creating_order/v1/commands/create_order.go similarity index 100% rename from internal/services/order_service/internal/orders/features/creating_order/v1/commands/create_order.go rename to internal/services/orderservice/internal/orders/features/creating_order/v1/commands/create_order.go diff --git a/internal/services/order_service/internal/orders/features/creating_order/v1/commands/create_order_handler.go b/internal/services/orderservice/internal/orders/features/creating_order/v1/commands/create_order_handler.go similarity index 98% rename from internal/services/order_service/internal/orders/features/creating_order/v1/commands/create_order_handler.go rename to internal/services/orderservice/internal/orders/features/creating_order/v1/commands/create_order_handler.go index 8956e662..fa3496f3 100644 --- a/internal/services/order_service/internal/orders/features/creating_order/v1/commands/create_order_handler.go +++ b/internal/services/orderservice/internal/orders/features/creating_order/v1/commands/create_order_handler.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/contracts/store" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" diff --git a/internal/services/order_service/internal/orders/features/creating_order/v1/dtos/create_order_request_dto.go b/internal/services/orderservice/internal/orders/features/creating_order/v1/dtos/create_order_request_dto.go similarity index 100% rename from internal/services/order_service/internal/orders/features/creating_order/v1/dtos/create_order_request_dto.go rename to internal/services/orderservice/internal/orders/features/creating_order/v1/dtos/create_order_request_dto.go diff --git a/internal/services/order_service/internal/orders/features/creating_order/v1/dtos/create_order_response_dto.go b/internal/services/orderservice/internal/orders/features/creating_order/v1/dtos/create_order_response_dto.go similarity index 100% rename from internal/services/order_service/internal/orders/features/creating_order/v1/dtos/create_order_response_dto.go rename to internal/services/orderservice/internal/orders/features/creating_order/v1/dtos/create_order_response_dto.go diff --git a/internal/services/order_service/internal/orders/features/creating_order/v1/endpoints/create_order_endpoint.go b/internal/services/orderservice/internal/orders/features/creating_order/v1/endpoints/create_order_endpoint.go similarity index 98% rename from internal/services/order_service/internal/orders/features/creating_order/v1/endpoints/create_order_endpoint.go rename to internal/services/orderservice/internal/orders/features/creating_order/v1/endpoints/create_order_endpoint.go index 5dff96b1..100be0c7 100644 --- a/internal/services/order_service/internal/orders/features/creating_order/v1/endpoints/create_order_endpoint.go +++ b/internal/services/orderservice/internal/orders/features/creating_order/v1/endpoints/create_order_endpoint.go @@ -6,7 +6,7 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/contracts/params" createOrderCommandV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/creating_order/v1/commands" diff --git a/internal/services/order_service/internal/orders/features/creating_order/v1/events/domain_events/order_created.go b/internal/services/orderservice/internal/orders/features/creating_order/v1/events/domain_events/order_created.go similarity index 98% rename from internal/services/order_service/internal/orders/features/creating_order/v1/events/domain_events/order_created.go rename to internal/services/orderservice/internal/orders/features/creating_order/v1/events/domain_events/order_created.go index 10848c72..c7de5061 100644 --- a/internal/services/order_service/internal/orders/features/creating_order/v1/events/domain_events/order_created.go +++ b/internal/services/orderservice/internal/orders/features/creating_order/v1/events/domain_events/order_created.go @@ -4,7 +4,7 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/domain" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" dtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/dtos/v1" domainExceptions "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/exceptions/domain_exceptions" diff --git a/internal/services/order_service/internal/orders/features/creating_order/v1/events/integration_events/order_created.go b/internal/services/orderservice/internal/orders/features/creating_order/v1/events/integration_events/order_created.go similarity index 100% rename from internal/services/order_service/internal/orders/features/creating_order/v1/events/integration_events/order_created.go rename to internal/services/orderservice/internal/orders/features/creating_order/v1/events/integration_events/order_created.go diff --git a/internal/services/order_service/internal/orders/features/getting_order_by_id/v1/dtos/get_order_by_id_request_dto.go b/internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/dtos/get_order_by_id_request_dto.go similarity index 100% rename from internal/services/order_service/internal/orders/features/getting_order_by_id/v1/dtos/get_order_by_id_request_dto.go rename to internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/dtos/get_order_by_id_request_dto.go diff --git a/internal/services/order_service/internal/orders/features/getting_order_by_id/v1/dtos/get_order_by_id_response_dto.go b/internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/dtos/get_order_by_id_response_dto.go similarity index 100% rename from internal/services/order_service/internal/orders/features/getting_order_by_id/v1/dtos/get_order_by_id_response_dto.go rename to internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/dtos/get_order_by_id_response_dto.go diff --git a/internal/services/order_service/internal/orders/features/getting_order_by_id/v1/endpoints/get_order_by_id_endpoint.go b/internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/endpoints/get_order_by_id_endpoint.go similarity index 98% rename from internal/services/order_service/internal/orders/features/getting_order_by_id/v1/endpoints/get_order_by_id_endpoint.go rename to internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/endpoints/get_order_by_id_endpoint.go index a1933b61..521c4031 100644 --- a/internal/services/order_service/internal/orders/features/getting_order_by_id/v1/endpoints/get_order_by_id_endpoint.go +++ b/internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/endpoints/get_order_by_id_endpoint.go @@ -5,7 +5,7 @@ import ( "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/contracts/params" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/dtos" diff --git a/internal/services/order_service/internal/orders/features/getting_order_by_id/v1/queries/get_order_by_id.go b/internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/queries/get_order_by_id.go similarity index 100% rename from internal/services/order_service/internal/orders/features/getting_order_by_id/v1/queries/get_order_by_id.go rename to internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/queries/get_order_by_id.go diff --git a/internal/services/order_service/internal/orders/features/getting_order_by_id/v1/queries/get_order_by_id_handler.go b/internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/queries/get_order_by_id_handler.go similarity index 98% rename from internal/services/order_service/internal/orders/features/getting_order_by_id/v1/queries/get_order_by_id_handler.go rename to internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/queries/get_order_by_id_handler.go index e2f4691e..b18201f6 100644 --- a/internal/services/order_service/internal/orders/features/getting_order_by_id/v1/queries/get_order_by_id_handler.go +++ b/internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/queries/get_order_by_id_handler.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" diff --git a/internal/services/order_service/internal/orders/features/getting_orders/v1/dtos/get_orders_request_dto.go b/internal/services/orderservice/internal/orders/features/getting_orders/v1/dtos/get_orders_request_dto.go similarity index 100% rename from internal/services/order_service/internal/orders/features/getting_orders/v1/dtos/get_orders_request_dto.go rename to internal/services/orderservice/internal/orders/features/getting_orders/v1/dtos/get_orders_request_dto.go diff --git a/internal/services/order_service/internal/orders/features/getting_orders/v1/dtos/get_orders_response_dto.go b/internal/services/orderservice/internal/orders/features/getting_orders/v1/dtos/get_orders_response_dto.go similarity index 100% rename from internal/services/order_service/internal/orders/features/getting_orders/v1/dtos/get_orders_response_dto.go rename to internal/services/orderservice/internal/orders/features/getting_orders/v1/dtos/get_orders_response_dto.go diff --git a/internal/services/order_service/internal/orders/features/getting_orders/v1/endpoints/get_orders_endpoint.go b/internal/services/orderservice/internal/orders/features/getting_orders/v1/endpoints/get_orders_endpoint.go similarity index 98% rename from internal/services/order_service/internal/orders/features/getting_orders/v1/endpoints/get_orders_endpoint.go rename to internal/services/orderservice/internal/orders/features/getting_orders/v1/endpoints/get_orders_endpoint.go index f441837e..f6dda661 100644 --- a/internal/services/order_service/internal/orders/features/getting_orders/v1/endpoints/get_orders_endpoint.go +++ b/internal/services/orderservice/internal/orders/features/getting_orders/v1/endpoints/get_orders_endpoint.go @@ -5,7 +5,7 @@ import ( "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/contracts/params" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/getting_orders/v1/dtos" diff --git a/internal/services/order_service/internal/orders/features/getting_orders/v1/queries/get_orders.go b/internal/services/orderservice/internal/orders/features/getting_orders/v1/queries/get_orders.go similarity index 100% rename from internal/services/order_service/internal/orders/features/getting_orders/v1/queries/get_orders.go rename to internal/services/orderservice/internal/orders/features/getting_orders/v1/queries/get_orders.go diff --git a/internal/services/order_service/internal/orders/features/getting_orders/v1/queries/get_orders_handler.go b/internal/services/orderservice/internal/orders/features/getting_orders/v1/queries/get_orders_handler.go similarity index 98% rename from internal/services/order_service/internal/orders/features/getting_orders/v1/queries/get_orders_handler.go rename to internal/services/orderservice/internal/orders/features/getting_orders/v1/queries/get_orders_handler.go index c5d41d83..5c49f43c 100644 --- a/internal/services/order_service/internal/orders/features/getting_orders/v1/queries/get_orders_handler.go +++ b/internal/services/orderservice/internal/orders/features/getting_orders/v1/queries/get_orders_handler.go @@ -3,7 +3,7 @@ package queries import ( "context" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" diff --git a/internal/services/order_service/internal/orders/features/submitting_order/v1/commands/submit_order.go b/internal/services/orderservice/internal/orders/features/submitting_order/v1/commands/submit_order.go similarity index 100% rename from internal/services/order_service/internal/orders/features/submitting_order/v1/commands/submit_order.go rename to internal/services/orderservice/internal/orders/features/submitting_order/v1/commands/submit_order.go diff --git a/internal/services/order_service/internal/orders/features/submitting_order/v1/events/domain_events/order_submitted.go b/internal/services/orderservice/internal/orders/features/submitting_order/v1/events/domain_events/order_submitted.go similarity index 91% rename from internal/services/order_service/internal/orders/features/submitting_order/v1/events/domain_events/order_submitted.go rename to internal/services/orderservice/internal/orders/features/submitting_order/v1/events/domain_events/order_submitted.go index 890e5baf..8ba117b2 100644 --- a/internal/services/order_service/internal/orders/features/submitting_order/v1/events/domain_events/order_submitted.go +++ b/internal/services/orderservice/internal/orders/features/submitting_order/v1/events/domain_events/order_submitted.go @@ -3,7 +3,7 @@ package domainEvents import ( "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" uuid "github.com/satori/go.uuid" ) diff --git a/internal/services/order_service/internal/orders/features/updating_shopping_card/v1/commands/update_shopping_card.go b/internal/services/orderservice/internal/orders/features/updating_shopping_card/v1/commands/update_shopping_card.go similarity index 100% rename from internal/services/order_service/internal/orders/features/updating_shopping_card/v1/commands/update_shopping_card.go rename to internal/services/orderservice/internal/orders/features/updating_shopping_card/v1/commands/update_shopping_card.go diff --git a/internal/services/order_service/internal/orders/features/updating_shopping_card/v1/events/shopping_card_updated.go b/internal/services/orderservice/internal/orders/features/updating_shopping_card/v1/events/shopping_card_updated.go similarity index 100% rename from internal/services/order_service/internal/orders/features/updating_shopping_card/v1/events/shopping_card_updated.go rename to internal/services/orderservice/internal/orders/features/updating_shopping_card/v1/events/shopping_card_updated.go diff --git a/internal/services/order_service/internal/orders/models/orders/aggregate/order.go b/internal/services/orderservice/internal/orders/models/orders/aggregate/order.go similarity index 99% rename from internal/services/order_service/internal/orders/models/orders/aggregate/order.go rename to internal/services/orderservice/internal/orders/models/orders/aggregate/order.go index 7b3f17d3..c228a46b 100644 --- a/internal/services/order_service/internal/orders/models/orders/aggregate/order.go +++ b/internal/services/orderservice/internal/orders/models/orders/aggregate/order.go @@ -8,7 +8,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/domain" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/errors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/models" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" dtosV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/dtos/v1" diff --git a/internal/services/order_service/internal/orders/models/orders/read_models/order_read.go b/internal/services/orderservice/internal/orders/models/orders/read_models/order_read.go similarity index 100% rename from internal/services/order_service/internal/orders/models/orders/read_models/order_read.go rename to internal/services/orderservice/internal/orders/models/orders/read_models/order_read.go diff --git a/internal/services/order_service/internal/orders/models/orders/read_models/shop_item_read.go b/internal/services/orderservice/internal/orders/models/orders/read_models/shop_item_read.go similarity index 100% rename from internal/services/order_service/internal/orders/models/orders/read_models/shop_item_read.go rename to internal/services/orderservice/internal/orders/models/orders/read_models/shop_item_read.go diff --git a/internal/services/order_service/internal/orders/models/orders/value_objects/shop_item.go b/internal/services/orderservice/internal/orders/models/orders/value_objects/shop_item.go similarity index 100% rename from internal/services/order_service/internal/orders/models/orders/value_objects/shop_item.go rename to internal/services/orderservice/internal/orders/models/orders/value_objects/shop_item.go diff --git a/internal/services/order_service/internal/orders/orders_fx.go b/internal/services/orderservice/internal/orders/orders_fx.go similarity index 98% rename from internal/services/order_service/internal/orders/orders_fx.go rename to internal/services/orderservice/internal/orders/orders_fx.go index e418fd82..c1ea96aa 100644 --- a/internal/services/order_service/internal/orders/orders_fx.go +++ b/internal/services/orderservice/internal/orders/orders_fx.go @@ -4,7 +4,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/web/route" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/eventstroredb" - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/data/repositories" createOrderV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/creating_order/v1/endpoints" getOrderByIdV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/features/getting_order_by_id/v1/endpoints" diff --git a/internal/services/order_service/internal/orders/projections/elastic_order_projection.go b/internal/services/orderservice/internal/orders/projections/elastic_order_projection.go similarity index 100% rename from internal/services/order_service/internal/orders/projections/elastic_order_projection.go rename to internal/services/orderservice/internal/orders/projections/elastic_order_projection.go diff --git a/internal/services/order_service/internal/orders/projections/mongo_order_projection.go b/internal/services/orderservice/internal/orders/projections/mongo_order_projection.go similarity index 99% rename from internal/services/order_service/internal/orders/projections/mongo_order_projection.go rename to internal/services/orderservice/internal/orders/projections/mongo_order_projection.go index 0c5fc68d..4679e8a1 100644 --- a/internal/services/order_service/internal/orders/projections/mongo_order_projection.go +++ b/internal/services/orderservice/internal/orders/projections/mongo_order_projection.go @@ -7,7 +7,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/producer" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/contracts/projection" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/es/models" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" diff --git a/internal/services/order_service/internal/shared/app/app.go b/internal/services/orderservice/internal/shared/app/app.go similarity index 100% rename from internal/services/order_service/internal/shared/app/app.go rename to internal/services/orderservice/internal/shared/app/app.go diff --git a/internal/services/order_service/internal/shared/app/application.go b/internal/services/orderservice/internal/shared/app/application.go similarity index 100% rename from internal/services/order_service/internal/shared/app/application.go rename to internal/services/orderservice/internal/shared/app/application.go diff --git a/internal/services/order_service/internal/shared/app/application_builder.go b/internal/services/orderservice/internal/shared/app/application_builder.go similarity index 100% rename from internal/services/order_service/internal/shared/app/application_builder.go rename to internal/services/orderservice/internal/shared/app/application_builder.go diff --git a/internal/services/order_service/internal/shared/app/test/test_app.go b/internal/services/orderservice/internal/shared/app/test/test_app.go similarity index 99% rename from internal/services/order_service/internal/shared/app/test/test_app.go rename to internal/services/orderservice/internal/shared/app/test/test_app.go index 7849d0ed..1d1ae048 100644 --- a/internal/services/order_service/internal/shared/app/test/test_app.go +++ b/internal/services/orderservice/internal/shared/app/test/test_app.go @@ -10,7 +10,7 @@ import ( config4 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/eventstroredb/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc" - config3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/config" + config3 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/bus" diff --git a/internal/services/order_service/internal/shared/app/test/test_application.go b/internal/services/orderservice/internal/shared/app/test/test_application.go similarity index 100% rename from internal/services/order_service/internal/shared/app/test/test_application.go rename to internal/services/orderservice/internal/shared/app/test/test_application.go diff --git a/internal/services/order_service/internal/shared/app/test/test_application_builder.go b/internal/services/orderservice/internal/shared/app/test/test_application_builder.go similarity index 100% rename from internal/services/order_service/internal/shared/app/test/test_application_builder.go rename to internal/services/orderservice/internal/shared/app/test/test_application_builder.go diff --git a/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go b/internal/services/orderservice/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go similarity index 100% rename from internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go rename to internal/services/orderservice/internal/shared/configurations/orders/infrastructure/infrastructure_configurator.go diff --git a/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_fx.go b/internal/services/orderservice/internal/shared/configurations/orders/infrastructure/infrastructure_fx.go similarity index 98% rename from internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_fx.go rename to internal/services/orderservice/internal/shared/configurations/orders/infrastructure/infrastructure_fx.go index f736ac5d..d3a510a4 100644 --- a/internal/services/order_service/internal/shared/configurations/orders/infrastructure/infrastructure_fx.go +++ b/internal/services/orderservice/internal/shared/configurations/orders/infrastructure/infrastructure_fx.go @@ -6,7 +6,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/eventstroredb" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/health" - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mongodb" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" diff --git a/internal/services/order_service/internal/shared/configurations/orders/orders_configurator.go b/internal/services/orderservice/internal/shared/configurations/orders/orders_configurator.go similarity index 98% rename from internal/services/order_service/internal/shared/configurations/orders/orders_configurator.go rename to internal/services/orderservice/internal/shared/configurations/orders/orders_configurator.go index 24d98ef5..2f435d1a 100644 --- a/internal/services/order_service/internal/shared/configurations/orders/orders_configurator.go +++ b/internal/services/orderservice/internal/shared/configurations/orders/orders_configurator.go @@ -5,7 +5,7 @@ import ( "net/http" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/orders/configurations" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/internal/shared/configurations/orders/infrastructure" diff --git a/internal/services/order_service/internal/shared/configurations/orders/orders_configurator_swagger.go b/internal/services/orderservice/internal/shared/configurations/orders/orders_configurator_swagger.go similarity index 93% rename from internal/services/order_service/internal/shared/configurations/orders/orders_configurator_swagger.go rename to internal/services/orderservice/internal/shared/configurations/orders/orders_configurator_swagger.go index 74c4be25..7f861a83 100644 --- a/internal/services/order_service/internal/shared/configurations/orders/orders_configurator_swagger.go +++ b/internal/services/orderservice/internal/shared/configurations/orders/orders_configurator_swagger.go @@ -1,7 +1,7 @@ package orders import ( - customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/custom_echo/contracts" + customEcho "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/customecho/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/orderservice/docs" "github.com/labstack/echo/v4" diff --git a/internal/services/order_service/internal/shared/configurations/orders/orders_fx.go b/internal/services/orderservice/internal/shared/configurations/orders/orders_fx.go similarity index 100% rename from internal/services/order_service/internal/shared/configurations/orders/orders_fx.go rename to internal/services/orderservice/internal/shared/configurations/orders/orders_fx.go diff --git a/internal/services/order_service/internal/shared/contracts/orders_metrics.go b/internal/services/orderservice/internal/shared/contracts/orders_metrics.go similarity index 100% rename from internal/services/order_service/internal/shared/contracts/orders_metrics.go rename to internal/services/orderservice/internal/shared/contracts/orders_metrics.go diff --git a/internal/services/order_service/internal/shared/grpc/genproto/orders.pb.go b/internal/services/orderservice/internal/shared/grpc/genproto/orders.pb.go similarity index 99% rename from internal/services/order_service/internal/shared/grpc/genproto/orders.pb.go rename to internal/services/orderservice/internal/shared/grpc/genproto/orders.pb.go index abccd5c3..9800c343 100644 --- a/internal/services/order_service/internal/shared/grpc/genproto/orders.pb.go +++ b/internal/services/orderservice/internal/shared/grpc/genproto/orders.pb.go @@ -2,7 +2,7 @@ // versions: // protoc-gen-go v1.26.0 // protoc v4.23.4 -// source: order_service/orders.proto +// source: orderservice/orders.proto package orders_service diff --git a/internal/services/order_service/internal/shared/grpc/genproto/orders_grpc.pb.go b/internal/services/orderservice/internal/shared/grpc/genproto/orders_grpc.pb.go similarity index 99% rename from internal/services/order_service/internal/shared/grpc/genproto/orders_grpc.pb.go rename to internal/services/orderservice/internal/shared/grpc/genproto/orders_grpc.pb.go index 6f5be25d..ba46c936 100644 --- a/internal/services/order_service/internal/shared/grpc/genproto/orders_grpc.pb.go +++ b/internal/services/orderservice/internal/shared/grpc/genproto/orders_grpc.pb.go @@ -2,7 +2,7 @@ // versions: // - protoc-gen-go-grpc v1.3.0 // - protoc v4.23.4 -// source: order_service/orders.proto +// source: orderservice/orders.proto package orders_service @@ -251,5 +251,5 @@ var OrdersService_ServiceDesc = grpc.ServiceDesc{ }, }, Streams: []grpc.StreamDesc{}, - Metadata: "order_service/orders.proto", + Metadata: "orderservice/orders.proto", } diff --git a/internal/services/order_service/internal/shared/grpc/order_grpc_service_server.go b/internal/services/orderservice/internal/shared/grpc/order_grpc_service_server.go similarity index 99% rename from internal/services/order_service/internal/shared/grpc/order_grpc_service_server.go rename to internal/services/orderservice/internal/shared/grpc/order_grpc_service_server.go index da09de3d..3919e517 100644 --- a/internal/services/order_service/internal/shared/grpc/order_grpc_service_server.go +++ b/internal/services/orderservice/internal/shared/grpc/order_grpc_service_server.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/http_errors/custom_errors" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" attribute2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" diff --git a/internal/services/order_service/internal/shared/test_fixtures/integration/integration_test_fixture.go b/internal/services/orderservice/internal/shared/test_fixtures/integration/integration_test_fixture.go similarity index 100% rename from internal/services/order_service/internal/shared/test_fixtures/integration/integration_test_fixture.go rename to internal/services/orderservice/internal/shared/test_fixtures/integration/integration_test_fixture.go diff --git a/internal/services/order_service/mocks/InvalidDeliveryAddressError.go b/internal/services/orderservice/mocks/InvalidDeliveryAddressError.go similarity index 100% rename from internal/services/order_service/mocks/InvalidDeliveryAddressError.go rename to internal/services/orderservice/mocks/InvalidDeliveryAddressError.go diff --git a/internal/services/order_service/mocks/InvalidEmailAddressError.go b/internal/services/orderservice/mocks/InvalidEmailAddressError.go similarity index 100% rename from internal/services/order_service/mocks/InvalidEmailAddressError.go rename to internal/services/orderservice/mocks/InvalidEmailAddressError.go diff --git a/internal/services/order_service/mocks/OrderElasticRepository.go b/internal/services/orderservice/mocks/OrderElasticRepository.go similarity index 100% rename from internal/services/order_service/mocks/OrderElasticRepository.go rename to internal/services/orderservice/mocks/OrderElasticRepository.go diff --git a/internal/services/order_service/mocks/OrderMongoRepository.go b/internal/services/orderservice/mocks/OrderMongoRepository.go similarity index 100% rename from internal/services/order_service/mocks/OrderMongoRepository.go rename to internal/services/orderservice/mocks/OrderMongoRepository.go diff --git a/internal/services/order_service/mocks/OrderNotFoundError.go b/internal/services/orderservice/mocks/OrderNotFoundError.go similarity index 100% rename from internal/services/order_service/mocks/OrderNotFoundError.go rename to internal/services/orderservice/mocks/OrderNotFoundError.go diff --git a/internal/services/order_service/mocks/OrderShopItemsRequiredError.go b/internal/services/orderservice/mocks/OrderShopItemsRequiredError.go similarity index 100% rename from internal/services/order_service/mocks/OrderShopItemsRequiredError.go rename to internal/services/orderservice/mocks/OrderShopItemsRequiredError.go diff --git a/internal/services/order_service/mocks/OrdersServiceClient.go b/internal/services/orderservice/mocks/OrdersServiceClient.go similarity index 100% rename from internal/services/order_service/mocks/OrdersServiceClient.go rename to internal/services/orderservice/mocks/OrdersServiceClient.go diff --git a/internal/services/order_service/mocks/OrdersServiceServer.go b/internal/services/orderservice/mocks/OrdersServiceServer.go similarity index 100% rename from internal/services/order_service/mocks/OrdersServiceServer.go rename to internal/services/orderservice/mocks/OrdersServiceServer.go diff --git a/internal/services/order_service/mocks/UnsafeOrdersServiceServer.go b/internal/services/orderservice/mocks/UnsafeOrdersServiceServer.go similarity index 100% rename from internal/services/order_service/mocks/UnsafeOrdersServiceServer.go rename to internal/services/orderservice/mocks/UnsafeOrdersServiceServer.go diff --git a/internal/services/order_service/mocks/orderReadRepository.go b/internal/services/orderservice/mocks/orderReadRepository.go similarity index 100% rename from internal/services/order_service/mocks/orderReadRepository.go rename to internal/services/orderservice/mocks/orderReadRepository.go diff --git a/internal/services/order_service/readme.md b/internal/services/orderservice/readme.md similarity index 100% rename from internal/services/order_service/readme.md rename to internal/services/orderservice/readme.md diff --git a/internal/services/order_service/revive-config.toml b/internal/services/orderservice/revive-config.toml similarity index 100% rename from internal/services/order_service/revive-config.toml rename to internal/services/orderservice/revive-config.toml diff --git a/internal/services/order_service/taskfile.yml b/internal/services/orderservice/taskfile.yml similarity index 100% rename from internal/services/order_service/taskfile.yml rename to internal/services/orderservice/taskfile.yml diff --git a/internal/services/order_service/taskfile_db.yml b/internal/services/orderservice/taskfile_db.yml similarity index 100% rename from internal/services/order_service/taskfile_db.yml rename to internal/services/orderservice/taskfile_db.yml diff --git a/internal/services/order_service/taskfile_test.yml b/internal/services/orderservice/taskfile_test.yml similarity index 100% rename from internal/services/order_service/taskfile_test.yml rename to internal/services/orderservice/taskfile_test.yml diff --git a/internal/services/order_service/test/end_to_end/orders/features/creating_order/v1/create_order_test.go b/internal/services/orderservice/test/end_to_end/orders/features/creating_order/v1/create_order_test.go similarity index 100% rename from internal/services/order_service/test/end_to_end/orders/features/creating_order/v1/create_order_test.go rename to internal/services/orderservice/test/end_to_end/orders/features/creating_order/v1/create_order_test.go diff --git a/internal/services/order_service/test/end_to_end/orders/features/getting_order_by_id/v1/get_order_by_id_test.go b/internal/services/orderservice/test/end_to_end/orders/features/getting_order_by_id/v1/get_order_by_id_test.go similarity index 100% rename from internal/services/order_service/test/end_to_end/orders/features/getting_order_by_id/v1/get_order_by_id_test.go rename to internal/services/orderservice/test/end_to_end/orders/features/getting_order_by_id/v1/get_order_by_id_test.go diff --git a/internal/services/order_service/test/end_to_end/orders/grpc/order_grpc_service_server_test.go b/internal/services/orderservice/test/end_to_end/orders/grpc/order_grpc_service_server_test.go similarity index 100% rename from internal/services/order_service/test/end_to_end/orders/grpc/order_grpc_service_server_test.go rename to internal/services/orderservice/test/end_to_end/orders/grpc/order_grpc_service_server_test.go diff --git a/internal/services/order_service/test/integration/orders/features/creating_order/v1/create_order_test.go b/internal/services/orderservice/test/integration/orders/features/creating_order/v1/create_order_test.go similarity index 100% rename from internal/services/order_service/test/integration/orders/features/creating_order/v1/create_order_test.go rename to internal/services/orderservice/test/integration/orders/features/creating_order/v1/create_order_test.go diff --git a/internal/services/order_service/test/integration/orders/features/getting_order_by_id/v1/get_order_by_id_test.go b/internal/services/orderservice/test/integration/orders/features/getting_order_by_id/v1/get_order_by_id_test.go similarity index 100% rename from internal/services/order_service/test/integration/orders/features/getting_order_by_id/v1/get_order_by_id_test.go rename to internal/services/orderservice/test/integration/orders/features/getting_order_by_id/v1/get_order_by_id_test.go diff --git a/taskfile.yml b/taskfile.yml index fd4323d2..45146538 100644 --- a/taskfile.yml +++ b/taskfile.yml @@ -11,33 +11,33 @@ tasks: run-catalogs-write-service: desc: Run catalog write service cmds: - - sh ./scripts/run.sh catalog_write_service + - sh ./scripts/run.sh catalogwriteservice run-catalog-read-service: desc: Run catalog read service cmds: - - sh ./scripts/run.sh catalog_read_service + - sh ./scripts/run.sh catalogreadservice run-order-service: desc: Run order service cmds: - - sh ./scripts/run.sh order_service + - sh ./scripts/run.sh orderservice build: desc: Build project components cmds: - sh ./scripts/build.sh pkg - - sh ./scripts/build.sh catalog_write_service - - sh ./scripts/build.sh catalog_read_service - - sh ./scripts/build.sh order_service + - sh ./scripts/build.sh catalogwriteservice + - sh ./scripts/build.sh catalogreadservice + - sh ./scripts/build.sh orderservice install-dependencies: desc: Install project dependencies cmds: - sh ./scripts/install-dependencies.sh pkg - - sh ./scripts/install-dependencies.sh catalog_write_service - - sh ./scripts/install-dependencies.sh catalog_read_service - - sh ./scripts/install-dependencies.sh order_service + - sh ./scripts/install-dependencies.sh catalogwriteservice + - sh ./scripts/install-dependencies.sh catalogreadservice + - sh ./scripts/install-dependencies.sh orderservice docker-compose-infra-up: desc: Start infrastructure using docker-compose @@ -52,51 +52,51 @@ tasks: openapi: desc: Generate OpenAPI documentation cmds: - - sh ./scripts/openapi.sh catalog_write_service - - sh ./scripts/openapi.sh catalog_read_service - - sh ./scripts/openapi.sh order_service + - sh ./scripts/openapi.sh catalogwriteservice + - sh ./scripts/openapi.sh catalogreadservice + - sh ./scripts/openapi.sh orderservice proto: desc: Generate protobuf files cmds: - - sh ./scripts/proto.sh catalog_write_service - - sh ./scripts/proto.sh order_service + - sh ./scripts/proto.sh catalogwriteservice + - sh ./scripts/proto.sh orderservice unit-test: desc: Run unit tests cmds: - - sh ./scripts/test.sh catalog_write_service unit - - sh ./scripts/test.sh catalog_read_service unit - - sh ./scripts/test.sh order_service unit + - sh ./scripts/test.sh catalogwriteservice unit + - sh ./scripts/test.sh catalogreadservice unit + - sh ./scripts/test.sh orderservice unit integration-test: desc: Run integration tests cmds: - - sh ./scripts/test.sh catalog_write_service integration - - sh ./scripts/test.sh catalog_read_service integration - - sh ./scripts/test.sh order_service integration + - sh ./scripts/test.sh catalogwriteservice integration + - sh ./scripts/test.sh catalogreadservice integration + - sh ./scripts/test.sh orderservice integration e2e-test: desc: Run end-to-end tests cmds: - - sh ./scripts/test.sh catalog_write_service e2e - - sh ./scripts/test.sh catalog_read_service e2e - - sh ./scripts/test.sh order_service e2e + - sh ./scripts/test.sh catalogwriteservice e2e + - sh ./scripts/test.sh catalogreadservice e2e + - sh ./scripts/test.sh orderservice e2e format: desc: Format codebase cmds: - - sh ./scripts/format.sh catalog_write_service - - sh ./scripts/format.sh catalog_read_service - - sh ./scripts/format.sh order_service + - sh ./scripts/format.sh catalogwriteservice + - sh ./scripts/format.sh catalogreadservice + - sh ./scripts/format.sh orderservice - sh ./scripts/format.sh pkg lint: desc: Run linters cmds: - - sh ./scripts/lint.sh catalog_write_service - - sh ./scripts/lint.sh catalog_read_service - - sh ./scripts/lint.sh order_service + - sh ./scripts/lint.sh catalogwriteservice + - sh ./scripts/lint.sh catalogreadservice + - sh ./scripts/lint.sh orderservice - sh ./scripts/lint.sh pkg pkg-mocks: @@ -109,6 +109,6 @@ tasks: services-mocks: desc: Generate service mocks cmds: - - cd internal/services/catalog_write_service && mockery --output mocks --all - - cd internal/services/catalog_read_service && mockery --output mocks --all - - cd internal/services/order_service && mockery --output mocks --all + - cd internal/services/catalogwriteservice && mockery --output mocks --all + - cd internal/services/catalogreadservice && mockery --output mocks --all + - cd internal/services/orderservice && mockery --output mocks --all From e6a5a516e40f655f42159b6520aaf060bec4ab37 Mon Sep 17 00:00:00 2001 From: Mehdi Hadeli Date: Mon, 18 Dec 2023 01:57:10 +0330 Subject: [PATCH 11/15] feat: :sparkles: supporting Inbox and Outbox Pattern #70 --- .../core/messaging/types/message_envelope.go | 20 +-- .../contratcs/message_serializer.go | 2 + .../core/serializer/json/event_serializer.go | 26 +--- .../serializer/json/message_serializer.go | 126 ++++++++++++++++++ internal/pkg/eventstroredb/esdb_serilizer.go | 2 +- ...sdb_subscription_check_point_repository.go | 2 +- .../postgres_message_service.go | 23 ++-- 7 files changed, 160 insertions(+), 41 deletions(-) diff --git a/internal/pkg/core/messaging/types/message_envelope.go b/internal/pkg/core/messaging/types/message_envelope.go index 26a8091f..f2a1ded1 100644 --- a/internal/pkg/core/messaging/types/message_envelope.go +++ b/internal/pkg/core/messaging/types/message_envelope.go @@ -1,12 +1,12 @@ package types type MessageEnvelope struct { - Message interface{} + Message IMessage Headers map[string]interface{} } func NewMessageEnvelope( - message interface{}, + message IMessage, headers map[string]interface{}, ) *MessageEnvelope { if headers == nil { @@ -19,19 +19,19 @@ func NewMessageEnvelope( } } -type MessageEnvelopeTMessage struct { +type MessageEnvelopeT[T IMessage] struct { *MessageEnvelope - MessageTMessage interface{} + Message T } -func NewMessageEnvelopeTMessage( - messageTMessage interface{}, +func NewMessageEnvelopeT[T IMessage]( + message T, headers map[string]interface{}, -) *MessageEnvelopeTMessage { - messageEnvelope := NewMessageEnvelope(messageTMessage, headers) +) *MessageEnvelopeT[T] { + messageEnvelope := NewMessageEnvelope(message, headers) - return &MessageEnvelopeTMessage{ + return &MessageEnvelopeT[T]{ MessageEnvelope: messageEnvelope, - MessageTMessage: messageTMessage, + Message: message, } } diff --git a/internal/pkg/core/serializer/contratcs/message_serializer.go b/internal/pkg/core/serializer/contratcs/message_serializer.go index 30682839..ee11561f 100644 --- a/internal/pkg/core/serializer/contratcs/message_serializer.go +++ b/internal/pkg/core/serializer/contratcs/message_serializer.go @@ -8,6 +8,8 @@ import ( type MessageSerializer interface { Serialize(message types.IMessage) (*EventSerializationResult, error) + SerializeObject(message interface{}) (*EventSerializationResult, error) + SerializeEnvelop(messageEnvelop types.MessageEnvelope) (*EventSerializationResult, error) Deserialize(data []byte, messageType string, contentType string) (types.IMessage, error) DeserializeObject(data []byte, messageType string, contentType string) (interface{}, error) DeserializeType(data []byte, messageType reflect.Type, contentType string) (types.IMessage, error) diff --git a/internal/pkg/core/serializer/json/event_serializer.go b/internal/pkg/core/serializer/json/event_serializer.go index 901a7f58..91e5d430 100644 --- a/internal/pkg/core/serializer/json/event_serializer.go +++ b/internal/pkg/core/serializer/json/event_serializer.go @@ -18,10 +18,6 @@ func NewDefaultEventJsonSerializer(serializer contratcs.Serializer) contratcs.Ev return &DefaultEventJsonSerializer{serializer: serializer} } -func (s *DefaultEventJsonSerializer) Serializer() contratcs.Serializer { - return s.serializer -} - func (s *DefaultEventJsonSerializer) Serialize(event domain.IDomainEvent) (*contratcs.EventSerializationResult, error) { return s.SerializeObject(event) } @@ -110,25 +106,13 @@ func (s *DefaultEventJsonSerializer) DeserializeType( // we use event short type name instead of full type name because this event in other receiver packages could have different package name eventTypeName := typeMapper.GetTypeName(eventType) - targetEventPointer := typeMapper.EmptyInstanceByTypeNameAndImplementedInterface[domain.IDomainEvent]( - eventTypeName, - ) - - if targetEventPointer == nil { - return nil, errors.Errorf("event type `%s` is not impelemted IDomainEvent or can't be instansiated", eventType) - } - - if contentType != s.ContentType() { - return nil, errors.Errorf("contentType: %s is not supported", contentType) - } - - if err := s.serializer.Unmarshal(data, targetEventPointer); err != nil { - return nil, errors.WrapIff(err, "error in Unmarshaling: `%s`", eventType) - } - - return targetEventPointer.(domain.IDomainEvent), nil + return s.Deserialize(data, eventTypeName, contentType) } func (s *DefaultEventJsonSerializer) ContentType() string { return "application/json" } + +func (s *DefaultEventJsonSerializer) Serializer() contratcs.Serializer { + return s.serializer +} diff --git a/internal/pkg/core/serializer/json/message_serializer.go b/internal/pkg/core/serializer/json/message_serializer.go index a5b981cc..9c612be0 100644 --- a/internal/pkg/core/serializer/json/message_serializer.go +++ b/internal/pkg/core/serializer/json/message_serializer.go @@ -1 +1,127 @@ package json + +import ( + "reflect" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/serializer/contratcs" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" + + "emperror.dev/errors" +) + +type DefaultMessageJsonSerializer struct { + serializer contratcs.Serializer +} + +func NewDefaultMessageJsonSerializer(serializer contratcs.Serializer) contratcs.MessageSerializer { + return &DefaultMessageJsonSerializer{serializer: serializer} +} + +func (m *DefaultMessageJsonSerializer) Serialize(message types.IMessage) (*contratcs.EventSerializationResult, error) { + return m.SerializeObject(message) +} + +func (m *DefaultMessageJsonSerializer) SerializeObject( + message interface{}, +) (*contratcs.EventSerializationResult, error) { + if message == nil { + return &contratcs.EventSerializationResult{Data: nil, ContentType: m.ContentType()}, nil + } + + // we use message short type name instead of full type name because this message in other receiver packages could have different package name + eventType := typeMapper.GetTypeName(message) + + data, err := m.serializer.Marshal(message) + if err != nil { + return nil, errors.WrapIff(err, "error in Marshaling: `%s`", eventType) + } + + result := &contratcs.EventSerializationResult{Data: data, ContentType: m.ContentType()} + + return result, nil +} + +func (m *DefaultMessageJsonSerializer) SerializeEnvelop( + messageEnvelop types.MessageEnvelope, +) (*contratcs.EventSerializationResult, error) { + // TODO implement me + panic("implement me") +} + +func (m *DefaultMessageJsonSerializer) Deserialize( + data []byte, + messageType string, + contentType string, +) (types.IMessage, error) { + if data == nil { + return nil, nil + } + + targetMessagePointer := typeMapper.EmptyInstanceByTypeNameAndImplementedInterface[types.IMessage]( + messageType, + ) + + if targetMessagePointer == nil { + return nil, errors.Errorf("message type `%s` is not impelemted IMessage or can't be instansiated", messageType) + } + + if contentType != m.ContentType() { + return nil, errors.Errorf("contentType: %s is not supported", contentType) + } + + if err := m.serializer.Unmarshal(data, targetMessagePointer); err != nil { + return nil, errors.WrapIff(err, "error in Unmarshaling: `%s`", messageType) + } + + return targetMessagePointer.(types.IMessage), nil +} + +func (m *DefaultMessageJsonSerializer) DeserializeObject( + data []byte, + messageType string, + contentType string, +) (interface{}, error) { + if data == nil { + return nil, nil + } + + targetMessagePointer := typeMapper.InstanceByTypeName(messageType) + + if targetMessagePointer == nil { + return nil, errors.Errorf("message type `%s` can't be instansiated", messageType) + } + + if contentType != m.ContentType() { + return nil, errors.Errorf("contentType: %s is not supported", contentType) + } + + if err := m.serializer.Unmarshal(data, targetMessagePointer); err != nil { + return nil, errors.WrapIff(err, "error in Unmarshaling: `%s`", messageType) + } + + return targetMessagePointer, nil +} + +func (m *DefaultMessageJsonSerializer) DeserializeType( + data []byte, + messageType reflect.Type, + contentType string, +) (types.IMessage, error) { + if data == nil { + return nil, nil + } + + // we use message short type name instead of full type name because this message in other receiver packages could have different package name + messageTypeName := typeMapper.GetTypeName(messageType) + + return m.Deserialize(data, messageTypeName, contentType) +} + +func (m *DefaultMessageJsonSerializer) ContentType() string { + return "application/json" +} + +func (m *DefaultMessageJsonSerializer) Serializer() contratcs.Serializer { + return m.serializer +} diff --git a/internal/pkg/eventstroredb/esdb_serilizer.go b/internal/pkg/eventstroredb/esdb_serilizer.go index a5cb1910..4714db3b 100644 --- a/internal/pkg/eventstroredb/esdb_serilizer.go +++ b/internal/pkg/eventstroredb/esdb_serilizer.go @@ -219,7 +219,7 @@ func (e *EsdbSerializer) SerializeObject( data interface{}, meta metadata.Metadata, ) (*esdb.EventData, error) { - serializedData, err := e.eventSerializer.Serialize(data) + serializedData, err := e.eventSerializer.SerializeObject(data) if err != nil { return nil, err } diff --git a/internal/pkg/eventstroredb/esdb_subscription_check_point_repository.go b/internal/pkg/eventstroredb/esdb_subscription_check_point_repository.go index ebcf09ad..1611c29c 100644 --- a/internal/pkg/eventstroredb/esdb_subscription_check_point_repository.go +++ b/internal/pkg/eventstroredb/esdb_subscription_check_point_repository.go @@ -98,7 +98,7 @@ func (e *esdbSubscriptionCheckpointRepository) Store( Event: events.NewEvent(typeMapper.GetTypeName(&CheckpointStored{})), } streamName := getCheckpointStreamName(subscriptionId) - eventData, err := e.esdbSerilizer.Serialize(checkpoint, nil) + eventData, err := e.esdbSerilizer.SerializeObject(checkpoint, nil) if err != nil { return errors.WrapIf(err, "esdbSerilizer.Serialize") } diff --git a/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service.go b/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service.go index ff38f9f5..ab060fd6 100644 --- a/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service.go +++ b/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "reflect" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/persistmessage" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/types" @@ -44,7 +43,7 @@ func (m *postgresMessageService) AddReceivedMessage(messageEnvelope types.Messag panic("implement me") } -func AddMessageCore( +func (m *postgresMessageService) AddMessageCore( ctx context.Context, messageEnvelope types.MessageEnvelope, deliveryType persistmessage.MessageDeliveryType, @@ -63,15 +62,23 @@ func AddMessageCore( id = uuid.NewV4().String() } - storeMessage := persistmessage.NewStoreMessage() + data, err := m.messageSerializer.SerializeEnvelop(messageEnvelope) + if err != nil { + return err + } - persistmessage.StoreMessage{ - ID: id, - TypeName: reflect.TypeOf(messageEnvelope.Message).Name(), - Serialized: _messageSerializer.Serialize(messageEnvelope), - DeliveryType: deliveryType, + uuidId, err := uuid.FromString(id) + if err != nil { + return err } + storeMessage := persistmessage.NewStoreMessage( + uuidId, + messageEnvelope.Message.GetMessageFullTypeName(), + string(data.Data), + deliveryType, + ) + err := _messagePersistenceRepository.AddAsync(storeMessage, cancellationToken) if err != nil { return err From 6c00afccb68e690d71cce31a90a8be3a82136a94 Mon Sep 17 00:00:00 2001 From: Mehdi Hadeli Date: Tue, 19 Dec 2023 00:58:25 +0330 Subject: [PATCH 12/15] refactor: :recycle: some refactoring in dbcontext #95 --- internal/pkg/logger/external/gromlog/gorm.go | 4 +- .../pipelines/mediator_metrics_pipeline.go | 2 +- internal/pkg/otel/tracing/utils/utils.go | 3 +- .../postgresgorm/contracts/gorm_dbcontext.go | 16 + .../pkg/postgresgorm/{db.go => gorm_db.go} | 4 +- internal/pkg/postgresgorm/gorm_postgres_fx.go | 1 + .../gormdbcontext/gorm_dbcontext.go | 93 +++++ .../gorm_dbcontext_extensions.go | 277 +++++++++++++++ .../gormdbcontext/gorm_dbcontext_test.go | 327 ++++++++++++++++++ .../gorm_extensions.go} | 2 +- .../mediator_transaction_pipeline.go | 4 +- .../repository/gorm_generic_repository.go | 2 +- .../message_persistence_dbcontext.go | 6 +- .../postgres_message_service_test.go | 149 +++++--- .../pkg/reflection/typemapper/type_mapper.go | 23 +- .../reflection/typemapper/type_mapper_test.go | 184 ++++++---- .../pkg/reflection/typemapper/unsafe_types.go | 2 +- .../mappings/mapping_profile.go | 4 +- .../product_data_model.go | 2 +- .../internal/products/dtos/v1/product_dto.go | 2 +- .../v1/create_product_handler.go | 8 +- .../v1/delete_product_handler.go | 4 +- .../v1/get_product_by_id_handler.go | 9 +- .../v1/get_products_handler.go | 8 +- .../v1/search_products_handler.go | 6 +- .../v1/update_product_handler.go | 15 +- .../catalogs/catalogs_configurator_seed.go | 2 +- .../data/dbcontext/catalogs_dbcontext.go | 248 +------------ .../data/dbcontext/catalogs_dbcontext_test.go | 55 ++- .../integration/integration_test_fixture.go | 4 +- .../unittest/unit_test_fixture.go | 50 +-- .../v1/get_product_by_id_test.go | 2 +- .../updatingproduct/v1/update_product_test.go | 2 +- .../v1/create_product_handler_unit_test.go | 9 +- .../v1/delete_product_handler_unit_test.go | 4 +- .../v1/get_product_by_id_handler_unit_test.go | 6 +- .../v1/update_product_handler_unit_test.go | 5 +- .../unit/products/mappings_profile_test.go | 6 +- 38 files changed, 1107 insertions(+), 443 deletions(-) create mode 100644 internal/pkg/postgresgorm/contracts/gorm_dbcontext.go rename internal/pkg/postgresgorm/{db.go => gorm_db.go} (98%) create mode 100644 internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext.go create mode 100644 internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext_extensions.go create mode 100644 internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext_test.go rename internal/pkg/postgresgorm/helpers/{helpers.go => gormextensions/gorm_extensions.go} (98%) rename internal/services/catalogwriteservice/internal/products/data/{models => datamodels}/product_data_model.go (97%) diff --git a/internal/pkg/logger/external/gromlog/gorm.go b/internal/pkg/logger/external/gromlog/gorm.go index e39f0f5c..4e488e81 100644 --- a/internal/pkg/logger/external/gromlog/gorm.go +++ b/internal/pkg/logger/external/gromlog/gorm.go @@ -21,11 +21,11 @@ func NewGormCustomLogger(logger logger.Logger) *GormCustomLogger { //cfg, err := config.ProvideLogConfig() // //var logger logger.logger - //if cfg.LogType == models.Logrus && err != nil { + //if cfg.LogType == datamodels.Logrus && err != nil { // logger = logrous.NewLogrusLogger(cfg, constants.Dev) //} else { // if err != nil { - // cfg = &config.LogOptions{LogLevel: "info", LogType: models.Zap} + // cfg = &config.LogOptions{LogLevel: "info", LogType: datamodels.Zap} // } // logger = zap.NewZapLogger(cfg, constants.Dev) //} diff --git a/internal/pkg/otel/metrics/mediatr/pipelines/mediator_metrics_pipeline.go b/internal/pkg/otel/metrics/mediatr/pipelines/mediator_metrics_pipeline.go index 03e7a5e9..f30828e1 100644 --- a/internal/pkg/otel/metrics/mediatr/pipelines/mediator_metrics_pipeline.go +++ b/internal/pkg/otel/metrics/mediatr/pipelines/mediator_metrics_pipeline.go @@ -9,7 +9,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants/telemetrytags" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics" customAttribute "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/attribute" - typemapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/mehdihadeli/go-mediatr" "go.opentelemetry.io/otel/attribute" diff --git a/internal/pkg/otel/tracing/utils/utils.go b/internal/pkg/otel/tracing/utils/utils.go index 4d64caa7..0d5acd15 100644 --- a/internal/pkg/otel/tracing/utils/utils.go +++ b/internal/pkg/otel/tracing/utils/utils.go @@ -8,6 +8,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/metadata" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/grpc/grpcerrors" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" + problemdetails "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/problemdetails" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/constants/telemetrytags" errorUtils "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils/errorutils" @@ -29,7 +30,7 @@ func HttpTraceStatusFromSpan(span trace.Span, err error) error { isError := err != nil if customErrors.IsCustomError(err) { - httpError := problemDetails.ParseError(err) + httpError := problemdetails.ParseError(err) return HttpTraceStatusFromSpanWithCode( span, diff --git a/internal/pkg/postgresgorm/contracts/gorm_dbcontext.go b/internal/pkg/postgresgorm/contracts/gorm_dbcontext.go new file mode 100644 index 00000000..9afeaf8b --- /dev/null +++ b/internal/pkg/postgresgorm/contracts/gorm_dbcontext.go @@ -0,0 +1,16 @@ +package contracts + +import ( + "context" + + "gorm.io/gorm" +) + +type IGormDBContext interface { + WithTx(ctx context.Context) (IGormDBContext, error) + WithTxIfExists(ctx context.Context) IGormDBContext + RunInTx(ctx context.Context, action ActionFunc) error + DB() *gorm.DB +} + +type ActionFunc func(ctx context.Context, gormContext IGormDBContext) error diff --git a/internal/pkg/postgresgorm/db.go b/internal/pkg/postgresgorm/gorm_db.go similarity index 98% rename from internal/pkg/postgresgorm/db.go rename to internal/pkg/postgresgorm/gorm_db.go index 24638ef0..c5672e1d 100644 --- a/internal/pkg/postgresgorm/db.go +++ b/internal/pkg/postgresgorm/gorm_db.go @@ -90,7 +90,9 @@ func createSQLLiteDB(dbFilePath string) (*gorm.DB, error) { return gormSQLLiteDB, err } -func NewSQLDB(orm *gorm.DB) (*sql.DB, error) { return orm.DB() } +func NewSQLDB(orm *gorm.DB) (*sql.DB, error) { + return orm.DB() +} func createPostgresDB(cfg *GormOptions) error { var db *sql.DB diff --git a/internal/pkg/postgresgorm/gorm_postgres_fx.go b/internal/pkg/postgresgorm/gorm_postgres_fx.go index 44fc6611..e994bcd7 100644 --- a/internal/pkg/postgresgorm/gorm_postgres_fx.go +++ b/internal/pkg/postgresgorm/gorm_postgres_fx.go @@ -16,6 +16,7 @@ var Module = fx.Module( provideConfig, NewGorm, NewSQLDB, + fx.Annotate( NewGormHealthChecker, fx.As(new(contracts.Health)), diff --git a/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext.go b/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext.go new file mode 100644 index 00000000..a23de298 --- /dev/null +++ b/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext.go @@ -0,0 +1,93 @@ +package gormdbcontext + +import ( + "context" + + defaultlogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers/gormextensions" + + "gorm.io/gorm" +) + +type gormDBContext struct { + db *gorm.DB +} + +func NewGormDBContext(db *gorm.DB) contracts.IGormDBContext { + c := &gormDBContext{db: db} + + return c +} + +func (c *gormDBContext) DB() *gorm.DB { + return c.db +} + +// WithTx creates a transactional DBContext with getting tx-gorm from the ctx. This will throw an error if the transaction does not exist. +func (c *gormDBContext) WithTx( + ctx context.Context, +) (contracts.IGormDBContext, error) { + tx, err := gormextensions.GetTxFromContext(ctx) + if err != nil { + return nil, err + } + + return NewGormDBContext(tx), nil +} + +// WithTxIfExists creates a transactional DBContext with getting tx-gorm from the ctx. not throw an error if the transaction is not existing and returns an existing database. +func (c *gormDBContext) WithTxIfExists( + ctx context.Context, +) contracts.IGormDBContext { + tx := gormextensions.GetTxFromContextIfExists(ctx) + if tx == nil { + return c + } + + return NewGormDBContext(tx) +} + +func (c *gormDBContext) RunInTx( + ctx context.Context, + action contracts.ActionFunc, +) error { + // https://gorm.io/docs/transactions.html#Transaction + tx := c.DB().WithContext(ctx).Begin() + + defaultlogger.GetLogger().Info("beginning database transaction") + + gormContext := gormextensions.SetTxToContext(ctx, tx) + ctx = gormContext + + defer func() { + if r := recover(); r != nil { + tx.WithContext(ctx).Rollback() + + if err, _ := r.(error); err != nil { + defaultlogger.GetLogger().Errorf( + "panic tn the transaction, rolling back transaction with panic err: %+v", + err, + ) + } else { + defaultlogger.GetLogger().Errorf("panic tn the transaction, rolling back transaction with panic message: %+v", r) + } + } + }() + + err := action(ctx, c) + if err != nil { + defaultlogger.GetLogger().Error("rolling back transaction") + tx.WithContext(ctx).Rollback() + + return err + } + + defaultlogger.GetLogger().Info("committing transaction") + + if err = tx.WithContext(ctx).Commit().Error; err != nil { + defaultlogger.GetLogger().Errorf("transaction commit error: %+v", err) + } + + return err +} diff --git a/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext_extensions.go b/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext_extensions.go new file mode 100644 index 00000000..16241a48 --- /dev/null +++ b/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext_extensions.go @@ -0,0 +1,277 @@ +package gormdbcontext + +import ( + "context" + "fmt" + + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" + defaultlogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/scopes" + typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" + + "github.com/iancoleman/strcase" + uuid "github.com/satori/go.uuid" +) + +func Exists[TDataModel interface{}]( + ctx context.Context, + dbContext contracts.IGormDBContext, + id uuid.UUID, +) bool { + var count int64 + + dataModel := typeMapper.GenericInstanceByT[TDataModel]() + + dbContext.DB().WithContext(ctx).Model(dataModel).Scopes(scopes.FilterByID(id)).Count(&count) + + return count > 0 +} + +func FindModelByID[TDataModel interface{}, TModel interface{}]( + ctx context.Context, + dbContext contracts.IGormDBContext, + id uuid.UUID, +) (TModel, error) { + var dataModel TDataModel + + // https://gorm.io/docs/query.html#Retrieving-objects-with-primary-key + // https://gorm.io/docs/query.html#Struct-amp-Map-Conditions + // https://gorm.io/docs/query.html#Inline-Condition + // https://gorm.io/docs/advanced_query.html + // result := c.WithContext(ctx).First(&dataModel, "id = ?", id) + // result := c.WithContext(ctx).First(&TDataModel{Id: id}) + // result := c.WithContext(ctx).Scopes(scopes.FilterByID(id)).First(&dataModel) + + modelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TModel]()) + dataModelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TDataModel]()) + + result := dbContext.DB().WithContext(ctx).First(&dataModel, id) + if result.Error != nil { + return *new(TModel), customErrors.NewNotFoundErrorWrap( + result.Error, + fmt.Sprintf( + "%s with id `%s` not found in the database", + dataModelName, + id.String(), + ), + ) + } + + defaultlogger.GetLogger().Infof("Number of affected rows are: %d", result.RowsAffected) + + resultModel, err := mapper.Map[TModel](dataModel) + if err != nil { + return *new(TModel), customErrors.NewInternalServerErrorWrap( + err, + fmt.Sprintf("error in the mapping %s", modelName), + ) + } + + return resultModel, nil +} + +func FindDataModelByID[TDataModel interface{}]( + ctx context.Context, + dbContext contracts.IGormDBContext, + id uuid.UUID, +) (TDataModel, error) { + var dataModel TDataModel + + // https://gorm.io/docs/query.html#Retrieving-objects-with-primary-key + // https://gorm.io/docs/query.html#Struct-amp-Map-Conditions + // https://gorm.io/docs/query.html#Inline-Condition + // https://gorm.io/docs/advanced_query.html + // result := c.WithContext(ctx).First(&dataModel, "id = ?", id) + // result := c.WithContext(ctx).First(&TDataModel{Id: id}) + // result := c.WithContext(ctx).Scopes(scopes.FilterByID(id)).First(&dataModel) + + dataModelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TDataModel]()) + + result := dbContext.DB().WithContext(ctx).First(&dataModel, id) + if result.Error != nil { + return *new(TDataModel), customErrors.NewNotFoundErrorWrap( + result.Error, + fmt.Sprintf( + "%s with id `%s` not found in the database", + dataModelName, + id.String(), + ), + ) + } + + defaultlogger.GetLogger().Infof("Number of affected rows are: %d", result.RowsAffected) + + return dataModel, nil +} + +// DeleteDataModelByID delete the data-model inner a tx if exists +func DeleteDataModelByID[TDataModel interface{}]( + ctx context.Context, + dbContext contracts.IGormDBContext, + id uuid.UUID, +) error { + txDBContext := dbContext.WithTxIfExists(ctx) + + dataModelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TDataModel]()) + + exists := Exists[TDataModel](ctx, dbContext, id) + if !exists { + return customErrors.NewNotFoundError(fmt.Sprintf("%s with id `%s` not found in the database", + dataModelName, + id.String(), + )) + } + + dataModel := typeMapper.GenericInstanceByT[TDataModel]() + + // https://gorm.io/docs/delete.html#Delete-a-Record + // https://gorm.io/docs/delete.html#Find-soft-deleted-records + // result := dbContext.WithContext(ctx).Delete(&TDataModel{Id: id}) + result := txDBContext.DB().WithContext(ctx).Delete(dataModel, id) + if result.Error != nil { + return customErrors.NewInternalServerErrorWrap( + result.Error, + fmt.Sprintf( + "error in deleting %s with id `%s` in the database", + dataModelName, + id.String(), + ), + ) + } + + defaultlogger.GetLogger().Infof("Number of affected rows are: %d", result.RowsAffected) + + return nil +} + +// AddModel add the model inner a tx if exists +func AddModel[TDataModel interface{}, TModel interface{}]( + ctx context.Context, + dbContext contracts.IGormDBContext, + model TModel, +) (TModel, error) { + txDBContext := dbContext.WithTxIfExists(ctx) + + dataModelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TDataModel]()) + modelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TModel]()) + + dataModel, err := mapper.Map[TDataModel](model) + if err != nil { + return *new(TModel), customErrors.NewInternalServerErrorWrap( + err, + fmt.Sprintf("error in the mapping %s", dataModelName), + ) + } + + // https://gorm.io/docs/create.html + result := txDBContext.DB().WithContext(ctx).Create(dataModel) + if result.Error != nil { + return *new(TModel), customErrors.NewConflictErrorWrap( + result.Error, + fmt.Sprintf("%s already exists", modelName), + ) + } + + defaultlogger.GetLogger().Infof("Number of affected rows are: %d", result.RowsAffected) + + resultModel, err := mapper.Map[TModel](dataModel) + if err != nil { + return *new(TModel), customErrors.NewInternalServerErrorWrap( + err, + fmt.Sprintf("error in the mapping %s", modelName), + ) + } + + return resultModel, err +} + +// AddDataModel add the data-model inner a tx if exists +func AddDataModel[TDataModel interface{}]( + ctx context.Context, + dbContext contracts.IGormDBContext, + dataModel TDataModel, +) (TDataModel, error) { + txDBContext := dbContext.WithTxIfExists(ctx) + + dataModelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TDataModel]()) + + // https://gorm.io/docs/create.html + result := txDBContext.DB().WithContext(ctx).Create(dataModel) + if result.Error != nil { + return *new(TDataModel), customErrors.NewConflictErrorWrap( + result.Error, + fmt.Sprintf("%s already exists", dataModelName), + ) + } + + defaultlogger.GetLogger().Infof("Number of affected rows are: %d", result.RowsAffected) + + return dataModel, nil +} + +// UpdateModel update the model inner a tx if exists +func UpdateModel[TDataModel interface{}, TModel interface{}]( + ctx context.Context, + dbContext contracts.IGormDBContext, + model TModel, +) (TModel, error) { + txDBContext := dbContext.WithTxIfExists(ctx) + + dataModelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TDataModel]()) + modelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TModel]()) + + dataModel, err := mapper.Map[TDataModel](model) + if err != nil { + return *new(TModel), customErrors.NewInternalServerErrorWrap( + err, + fmt.Sprintf("error in the mapping %s", dataModelName), + ) + } + + // https://gorm.io/docs/update.html + result := txDBContext.DB().WithContext(ctx).Updates(dataModel) + if result.Error != nil { + return *new(TModel), customErrors.NewInternalServerErrorWrap( + result.Error, + fmt.Sprintf("error in updating the %s", modelName), + ) + } + + defaultlogger.GetLogger().Infof("Number of affected rows are: %d", result.RowsAffected) + + modelResult, err := mapper.Map[TModel](dataModel) + if err != nil { + return *new(TModel), customErrors.NewInternalServerErrorWrap( + err, + fmt.Sprintf("error in the mapping %s", modelName), + ) + } + + return modelResult, err +} + +// UpdateDataModel update the data-model inner a tx if exists +func UpdateDataModel[TDataModel interface{}]( + ctx context.Context, + dbContext contracts.IGormDBContext, + dataModel TDataModel, +) (TDataModel, error) { + txDBContext := dbContext.WithTxIfExists(ctx) + + dataModelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TDataModel]()) + + // https://gorm.io/docs/update.html + result := txDBContext.DB().WithContext(ctx).Updates(dataModel) + if result.Error != nil { + return *new(TDataModel), customErrors.NewInternalServerErrorWrap( + result.Error, + fmt.Sprintf("error in updating the %s", dataModelName), + ) + } + + defaultlogger.GetLogger().Infof("Number of affected rows are: %d", result.RowsAffected) + + return dataModel, nil +} diff --git a/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext_test.go b/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext_test.go new file mode 100644 index 00000000..3caf6212 --- /dev/null +++ b/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext_test.go @@ -0,0 +1,327 @@ +//go:build unit +// +build unit + +package gormdbcontext + +import ( + "context" + "os" + "testing" + "time" + + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/scopes" + + "emperror.dev/errors" + "github.com/brianvoe/gofakeit/v6" + "github.com/goccy/go-json" + uuid "github.com/satori/go.uuid" + "github.com/stretchr/testify/suite" + "go.uber.org/fx" + "go.uber.org/fx/fxtest" + "gorm.io/gorm" +) + +// ProductDataModel data model +type ProductDataModel struct { + Id uuid.UUID `gorm:"primaryKey"` + Name string + Description string + Price float64 + CreatedAt time.Time `gorm:"default:current_timestamp"` + UpdatedAt time.Time + // for soft delete - https://gorm.io/docs/delete.html#Soft-Delete + gorm.DeletedAt +} + +// TableName overrides the table name used by ProductDataModel to `products` - https://gorm.io/docs/conventions.html#TableName +func (p *ProductDataModel) TableName() string { + return "products" +} + +func (p *ProductDataModel) String() string { + j, _ := json.Marshal(p) + + return string(j) +} + +// Product model +type Product struct { + Id uuid.UUID + Name string + Description string + Price float64 + CreatedAt time.Time + UpdatedAt time.Time +} + +// Define the suite +type GormDBContextTestSuite struct { + suite.Suite + items []*ProductDataModel + dbContext contracts.IGormDBContext + app *fxtest.App + dbFilePath string +} + +// In order for 'go test' to run this suite, we need to create +// a normal test function and pass our suite to suite.Run +func TestGormDBContext(t *testing.T) { + suite.Run(t, new(GormDBContextTestSuite)) +} + +func (s *GormDBContextTestSuite) Test_FindProductByID() { + s.Require().NotNil(s.dbContext) + + id := s.items[0].Id + + p, err := FindModelByID[*ProductDataModel, *Product]( + context.Background(), + s.dbContext, + id, + ) + s.Require().NoError(err) + s.Require().NotNil(p) + + s.Assert().Equal(p.Id, id) +} + +func (s *GormDBContextTestSuite) Test_ExistsProductByID() { + s.Require().NotNil(s.dbContext) + + id := s.items[0].Id + + exist := Exists[*ProductDataModel]( + context.Background(), + s.dbContext, + id, + ) + + s.Require().True(exist) +} + +func (s *GormDBContextTestSuite) Test_NoneExistsProductByID() { + s.Require().NotNil(s.dbContext) + + id := uuid.NewV4() + + exist := Exists[*ProductDataModel]( + context.Background(), + s.dbContext, + id, + ) + + s.Require().False(exist) +} + +func (s *GormDBContextTestSuite) Test_DeleteProductByID() { + s.Require().NotNil(s.dbContext) + + id := s.items[0].Id + + err := DeleteDataModelByID[*ProductDataModel]( + context.Background(), + s.dbContext, + id, + ) + s.Require().NoError(err) + + p, err := FindModelByID[*ProductDataModel, *Product]( + context.Background(), + s.dbContext, + id, + ) + s.Require().Error(err) + s.Require().Nil(p) + + // https://gorm.io/docs/delete.html#Find-soft-deleted-records + var softDeletedProduct *ProductDataModel + s.dbContext.DB().Scopes(scopes.FilterAllItemsWithSoftDeleted).First(&softDeletedProduct, id) + s.Require().NotNil(softDeletedProduct) + + var deletedCount int64 + var allCount int64 + + // https://gorm.io/docs/advanced_query.html#Count + s.dbContext.DB().Model(&ProductDataModel{}).Scopes(scopes.FilterAllItemsWithSoftDeleted).Count(&allCount) + s.Equal(allCount, int64(2)) + + s.dbContext.DB().Model(&ProductDataModel{}).Scopes(scopes.SoftDeleted).Count(&deletedCount) + s.Equal(deletedCount, int64(1)) +} + +func (s *GormDBContextTestSuite) Test_CreateProduct() { + s.Require().NotNil(s.dbContext) + + item := &Product{ + Id: uuid.NewV4(), + Name: gofakeit.Name(), + Description: gofakeit.AdjectiveDescriptive(), + Price: gofakeit.Price(100, 1000), + } + + res, err := AddModel[*ProductDataModel, *Product](context.Background(), s.dbContext, item) + s.Require().NoError(err) + + p, err := FindModelByID[*ProductDataModel, *Product]( + context.Background(), + s.dbContext, + item.Id, + ) + s.Require().NoError(err) + s.Require().NotNil(p) + + s.Assert().Equal(p.Id, item.Id) + s.Assert().Equal(p.Id, res.Id) +} + +func (s *GormDBContextTestSuite) Test_UpdateProduct() { + s.Require().NotNil(s.dbContext) + + id := s.items[0].Id + + p, err := FindModelByID[*ProductDataModel, *Product]( + context.Background(), + s.dbContext, + id, + ) + s.Require().NoError(err) + + newName := gofakeit.Name() + item := p + item.Name = newName + + res, err := UpdateModel[*ProductDataModel, *Product](context.Background(), s.dbContext, item) + s.Require().NoError(err) + + p2, err := FindModelByID[*ProductDataModel, *Product]( + context.Background(), + s.dbContext, + id, + ) + s.Require().NoError(err) + + s.Assert().Equal(item.Name, p2.Name) + s.Assert().Equal(res.Name, p2.Name) +} + +// TestSuite Hooks + +func (s *GormDBContextTestSuite) SetupTest() { + err := ConfigureProductsMappings() + s.Require().NoError(err) + + var gormDBContext contracts.IGormDBContext + var gormOptions *gormPostgres.GormOptions + + app := fxtest.New( + s.T(), + config.ModuleFunc(environment.Test), + zap.Module, + fxlog.FxLogger, + gormPostgres.Module, + fx.Provide(NewGormDBContext), + fx.Decorate( + func(cfg *gormPostgres.GormOptions) (*gormPostgres.GormOptions, error) { + // using sql-lite with a database file + cfg.UseSQLLite = true + + return cfg, nil + }, + ), + fx.Populate(&gormDBContext), + fx.Populate(&gormOptions), + ).RequireStart() + + s.app = app + s.dbContext = gormDBContext + s.dbFilePath = gormOptions.Dns() + + s.initDB() +} + +func (s *GormDBContextTestSuite) TearDownTest() { + err := s.cleanupDB() + s.Require().NoError(err) + + mapper.ClearMappings() + + s.app.RequireStop() +} + +func (s *GormDBContextTestSuite) initDB() { + err := migrateGorm(s.dbContext.DB()) + s.Require().NoError(err) + + products, err := seedData(s.dbContext.DB()) + s.Require().NoError(err) + + s.items = products +} + +func (s *GormDBContextTestSuite) cleanupDB() error { + sqldb, _ := s.dbContext.DB().DB() + e := sqldb.Close() + s.Require().NoError(e) + + // removing sql-lite file + err := os.Remove(s.dbFilePath) + + return err +} + +func migrateGorm(db *gorm.DB) error { + err := db.AutoMigrate(&ProductDataModel{}) + if err != nil { + return err + } + + return nil +} + +func seedData(gormDB *gorm.DB) ([]*ProductDataModel, error) { + products := []*ProductDataModel{ + { + Id: uuid.NewV4(), + Name: gofakeit.Name(), + CreatedAt: time.Now(), + Description: gofakeit.AdjectiveDescriptive(), + Price: gofakeit.Price(100, 1000), + }, + { + Id: uuid.NewV4(), + Name: gofakeit.Name(), + CreatedAt: time.Now(), + Description: gofakeit.AdjectiveDescriptive(), + Price: gofakeit.Price(100, 1000), + }, + } + + // seed data + err := gormDB.CreateInBatches(products, len(products)).Error + if err != nil { + return nil, errors.Wrap(err, "error in seed database") + } + + return products, nil +} + +func ConfigureProductsMappings() error { + err := mapper.CreateMap[*ProductDataModel, *Product]() + if err != nil { + return err + } + + err = mapper.CreateMap[*Product, *ProductDataModel]() + if err != nil { + return err + } + + return nil +} diff --git a/internal/pkg/postgresgorm/helpers/helpers.go b/internal/pkg/postgresgorm/helpers/gormextensions/gorm_extensions.go similarity index 98% rename from internal/pkg/postgresgorm/helpers/helpers.go rename to internal/pkg/postgresgorm/helpers/gormextensions/gorm_extensions.go index 888877d8..3780df15 100644 --- a/internal/pkg/postgresgorm/helpers/helpers.go +++ b/internal/pkg/postgresgorm/helpers/gormextensions/gorm_extensions.go @@ -1,4 +1,4 @@ -package helpers +package gormextensions import ( "context" diff --git a/internal/pkg/postgresgorm/mediatr/pipelines/mediator_transaction_pipeline.go b/internal/pkg/postgresgorm/mediatr/pipelines/mediator_transaction_pipeline.go index b63a2d4a..7517f304 100644 --- a/internal/pkg/postgresgorm/mediatr/pipelines/mediator_transaction_pipeline.go +++ b/internal/pkg/postgresgorm/mediatr/pipelines/mediator_transaction_pipeline.go @@ -5,7 +5,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers/gormextensions" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/mehdihadeli/go-mediatr" @@ -49,7 +49,7 @@ func (m *mediatorTransactionPipeline) Handle( requestName, ) - gormContext := helpers.SetTxToContext(ctx, tx) + gormContext := gormextensions.SetTxToContext(ctx, tx) ctx = gormContext defer func() { diff --git a/internal/pkg/postgresgorm/repository/gorm_generic_repository.go b/internal/pkg/postgresgorm/repository/gorm_generic_repository.go index 2f5c8b77..8dee62a2 100644 --- a/internal/pkg/postgresgorm/repository/gorm_generic_repository.go +++ b/internal/pkg/postgresgorm/repository/gorm_generic_repository.go @@ -10,7 +10,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/data/specification" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers/gormextensions" reflectionHelper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/reflectionhelper" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" diff --git a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go b/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go index 16de7c6e..9f340f1a 100644 --- a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go +++ b/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go @@ -3,7 +3,7 @@ package messagepersistence import ( "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers/gormextensions" "gorm.io/gorm" ) @@ -26,7 +26,7 @@ func NewPostgresMessagePersistenceDBContext( func (c *PostgresMessagePersistenceDBContext) WithTx( ctx context.Context, ) (*PostgresMessagePersistenceDBContext, error) { - tx, err := helpers.GetTxFromContext(ctx) + tx, err := gormextensions.GetTxFromContext(ctx) if err != nil { return nil, err } @@ -38,7 +38,7 @@ func (c *PostgresMessagePersistenceDBContext) WithTx( func (c *PostgresMessagePersistenceDBContext) WithTxIfExists( ctx context.Context, ) *PostgresMessagePersistenceDBContext { - tx := helpers.GetTxFromContextIfExists(ctx) + tx := gormextensions.GetTxFromContextIfExists(ctx) if tx == nil { return c } diff --git a/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service_test.go b/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service_test.go index fd0680ec..3bb4a967 100644 --- a/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service_test.go +++ b/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service_test.go @@ -1,19 +1,30 @@ +//go:build unit +// +build unit + package messagepersistence import ( "context" + "os" "testing" "time" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/persistmessage" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/fxlog" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" - gorm2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/containers/testcontainer/gorm" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers/gormextensions" + "emperror.dev/errors" uuid "github.com/satori/go.uuid" "github.com/stretchr/testify/suite" + "go.uber.org/fx" + "go.uber.org/fx/fxtest" "gorm.io/gorm" ) @@ -25,6 +36,8 @@ type postgresMessageServiceTest struct { dbContext *PostgresMessagePersistenceDBContext storeMessages []*persistmessage.StoreMessage ctx context.Context + dbFilePath string + app *fxtest.App } func TestPostgresMessageService(t *testing.T) { @@ -34,47 +47,107 @@ func TestPostgresMessageService(t *testing.T) { ) } -func (c *postgresMessageServiceTest) SetupSuite() { - opts, err := gorm2.NewGormTestContainers(defaultLogger.GetLogger()). - PopulateContainerOptions(context.Background(), c.T()) - c.Require().NoError(err) +//func (c *postgresMessageServiceTest) SetupSuite() { +// opts, err := gorm2.NewGormTestContainers(defaultLogger.GetLogger()). +// PopulateContainerOptions(context.Background(), c.T()) +// c.Require().NoError(err) +// +// gormDB, err := postgresgorm.NewGorm(opts) +// c.Require().NoError(err) +// c.DB = gormDB +// +// err = migrationDatabase(gormDB) +// c.Require().NoError(err) +// +// c.dbContext = NewPostgresMessagePersistenceDBContext(gormDB) +// c.messagingRepository = NewPostgresMessageService( +// c.dbContext, +// defaultLogger.GetLogger(), +// ) +//} - gormDB, err := postgresgorm.NewGorm(opts) - c.Require().NoError(err) - c.DB = gormDB +func (c *postgresMessageServiceTest) SetupTest() { + var gormDBContext *PostgresMessagePersistenceDBContext + var gormOptions *postgresgorm.GormOptions + + app := fxtest.New( + c.T(), + config.ModuleFunc(environment.Test), + zap.Module, + fxlog.FxLogger, + postgresgorm.Module, + fx.Decorate( + func(cfg *postgresgorm.GormOptions) (*postgresgorm.GormOptions, error) { + // using sql-lite with a database file + cfg.UseSQLLite = true + + return cfg, nil + }, + ), + fx.Provide(NewPostgresMessagePersistenceDBContext), + fx.Populate(&gormDBContext), + fx.Populate(&gormOptions), + ).RequireStart() + + c.dbContext = gormDBContext + c.dbFilePath = gormOptions.Dns() + c.app = app + + c.initDB() +} - err = migrationDatabase(gormDB) +func (c *postgresMessageServiceTest) TearDownTest() { + err := c.cleanupDB() c.Require().NoError(err) - c.dbContext = NewPostgresMessagePersistenceDBContext(gormDB) - c.messagingRepository = NewPostgresMessageService( - c.dbContext, - defaultLogger.GetLogger(), - ) + mapper.ClearMappings() + + c.app.RequireStop() } -func (c *postgresMessageServiceTest) SetupTest() { - ctx := context.Background() - c.ctx = ctx - p, err := seedData(context.Background(), c.DB) +func (c *postgresMessageServiceTest) initDB() { + err := migrateGorm(c.dbContext.DB) c.Require().NoError(err) - c.storeMessages = p -} -func (c *postgresMessageServiceTest) TearDownTest() { - err := c.cleanupPostgresData() + storeMessages, err := seedData(c.dbContext.DB) c.Require().NoError(err) + + c.storeMessages = storeMessages } +func (c *postgresMessageServiceTest) cleanupDB() error { + sqldb, _ := c.dbContext.DB.DB() + e := sqldb.Close() + c.Require().NoError(e) + + // removing sql-lite file + err := os.Remove(s.dbFilePath) + + return err +} + +//func (c *postgresMessageServiceTest) SetupTest() { +// ctx := context.Background() +// c.ctx = ctx +// p, err := seedData(context.Background(), c.DB) +// c.Require().NoError(err) +// c.storeMessages = p +//} +// +//func (c *postgresMessageServiceTest) TearDownTest() { +// err := c.cleanupPostgresData() +// c.Require().NoError(err) +//} + func (c *postgresMessageServiceTest) BeginTx() { c.logger.Info("starting transaction") tx := c.dbContext.Begin() - gormContext := helpers.SetTxToContext(c.ctx, tx) + gormContext := gormextensions.SetTxToContext(c.ctx, tx) c.ctx = gormContext } func (c *postgresMessageServiceTest) CommitTx() { - tx := helpers.GetTxFromContextIfExists(c.ctx) + tx := gormextensions.GetTxFromContextIfExists(c.ctx) if tx != nil { c.logger.Info("committing transaction") tx.Commit() @@ -87,7 +160,7 @@ func (c *postgresMessageServiceTest) Test_Add() { MessageStatus: persistmessage.Processed, Data: "test data 3", DataType: "string", - Created: time.Now(), + CreatedAt: time.Now(), DeliveryType: persistmessage.Outbox, } @@ -106,7 +179,7 @@ func (c *postgresMessageServiceTest) Test_Add() { c.Assert().Equal(message.ID, m.ID) } -func migrationDatabase(db *gorm.DB) error { +func migrateGorm(db *gorm.DB) error { err := db.AutoMigrate(&persistmessage.StoreMessage{}) if err != nil { return err @@ -116,7 +189,6 @@ func migrationDatabase(db *gorm.DB) error { } func seedData( - ctx context.Context, db *gorm.DB, ) ([]*persistmessage.StoreMessage, error) { messages := []*persistmessage.StoreMessage{ @@ -125,7 +197,7 @@ func seedData( MessageStatus: persistmessage.Processed, Data: "test data", DataType: "string", - Created: time.Now(), + CreatedAt: time.Now(), DeliveryType: persistmessage.Outbox, }, { @@ -133,27 +205,16 @@ func seedData( MessageStatus: persistmessage.Processed, Data: "test data 2", DataType: "string", - Created: time.Now(), + CreatedAt: time.Now(), DeliveryType: persistmessage.Outbox, }, } - err := db.WithContext(ctx).Create(messages).Error + // seed data + err := db.CreateInBatches(messages, len(messages)).Error if err != nil { - return nil, err + return nil, errors.Wrap(err, "error in seed database") } return messages, nil } - -func (c *postgresMessageServiceTest) cleanupPostgresData() error { - tables := []string{"store_messages"} - // Iterate over the tables and delete all records - for _, table := range tables { - err := c.DB.Exec("DELETE FROM " + table).Error - - return err - } - - return nil -} diff --git a/internal/pkg/reflection/typemapper/type_mapper.go b/internal/pkg/reflection/typemapper/type_mapper.go index e380a262..f35ef4a3 100644 --- a/internal/pkg/reflection/typemapper/type_mapper.go +++ b/internal/pkg/reflection/typemapper/type_mapper.go @@ -1,4 +1,4 @@ -package typeMapper +package typemapper // https://stackoverflow.com/a/34722791/581476 // https://stackoverflow.com/questions/7850140/how-do-you-create-a-new-instance-of-a-struct-from-its-type-at-run-time-in-go @@ -184,8 +184,7 @@ func GetTypeName(input interface{}) string { return fmt.Sprintf("*%s", t.Elem().Name()) } -// GetNonePointerTypeName returns the name of the type without its package name and its pointer -func GetNonePointerTypeName(input interface{}) string { +func GetSnakeTypeName(input interface{}) string { if input == nil { return "" } @@ -195,10 +194,10 @@ func GetNonePointerTypeName(input interface{}) string { return t.Name() } - return t.Elem().Name() + return strcase.ToSnake(t.Elem().Name()) } -func GetSnakeTypeName(input interface{}) string { +func GetKebabTypeName(input interface{}) string { if input == nil { return "" } @@ -208,7 +207,7 @@ func GetSnakeTypeName(input interface{}) string { return t.Name() } - return strcase.ToSnake(t.Elem().Name()) + return strcase.ToKebab(t.Elem().Name()) } func GetTypeNameByT[T any]() string { @@ -220,7 +219,17 @@ func GetTypeNameByT[T any]() string { return fmt.Sprintf("*%s", t.Elem().Name()) } -func GetNonPointerTypeName(input interface{}) string { +func GetNonePointerTypeNameByT[T any]() string { + t := reflect.TypeOf((*T)(nil)).Elem() + if t.Kind() != reflect.Ptr { + return t.Name() + } + + return t.Elem().Name() +} + +// GetNonePointerTypeName returns the name of the type without its package name and its pointer +func GetNonePointerTypeName(input interface{}) string { if input == nil { return "" } diff --git a/internal/pkg/reflection/typemapper/type_mapper_test.go b/internal/pkg/reflection/typemapper/type_mapper_test.go index 6a9d515a..5a372fef 100644 --- a/internal/pkg/reflection/typemapper/type_mapper_test.go +++ b/internal/pkg/reflection/typemapper/type_mapper_test.go @@ -1,87 +1,141 @@ -package typeMapper +//go:build unit +// +build unit + +package typemapper import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -func TestTypes(t *testing.T) { - s := Test{A: 10} - s2 := &Test{A: 10} +func Test_GetTypeNameByT(t *testing.T) { + pointerTypeName := GetTypeNameByT[*Test]() + nonePointerTypeName := GetTypeNameByT[Test]() - q2 := TypeByName("*typeMapper.Test") - q22 := InstanceByTypeName("*typeMapper.Test").(*Test) - q222 := InstancePointerByTypeName("*typeMapper.Test").(*Test) - q3 := TypeByNameAndImplementedInterface[ITest]("*typeMapper.Test") - q4 := EmptyInstanceByTypeNameAndImplementedInterface[ITest]("*typeMapper.Test") + require.Equal(t, pointerTypeName, "*Test") + require.Equal(t, nonePointerTypeName, "Test") +} - c1 := GetTypeFromGeneric[Test]() - c2 := GetTypeFromGeneric[*Test]() - c3 := GetTypeFromGeneric[ITest]() +func Test_GetNonePointerTypeNameByT(t *testing.T) { + pointerTypeName := GetNonePointerTypeNameByT[*Test]() + nonePointerTypeName := GetNonePointerTypeNameByT[Test]() - d1 := GetReflectType(Test{}) - d2 := GetReflectType(&Test{}) - d3 := GetReflectType((*ITest)(nil)) + require.Equal(t, pointerTypeName, "Test") + require.Equal(t, nonePointerTypeName, "Test") +} - q := TypeByName("typeMapper.Test") - q1 := InstanceByTypeName("typeMapper.Test").(Test) - q11 := InstancePointerByTypeName("typeMapper.Test").(*Test) +func Test_TypeByName(t *testing.T) { + s1 := TypeByName("*typeMapper.Test") + s2 := TypeByName("typeMapper.Test") + s3 := TypeByName("*Test") + s4 := TypeByName("Test") - y := TypeByName("*Test") - y1 := InstanceByTypeName("*Test").(*Test) - y2 := InstancePointerByTypeName("*Test").(*Test) + assert.NotNil(t, s1) + assert.NotNil(t, s2) + assert.NotNil(t, s3) + assert.NotNil(t, s4) +} - z := TypeByName("Test") - z1 := InstanceByTypeName("Test").(Test) - z2 := InstancePointerByTypeName("Test").(*Test) +func Test_GetTypeName(t *testing.T) { + t1 := Test{A: 10} + t2 := &Test{A: 10} - r := GenericInstanceByT[*Test]() - r2 := GenericInstanceByT[Test]() + typeName1 := GetTypeName(t1) + typeName2 := GetTypeName(t2) - typeName := GetFullTypeName(s) - typeName2 := GetFullTypeName(s2) - typeName3 := GetTypeName(s2) - typeName4 := GetTypeName(s) + assert.Equal(t, "Test", typeName1) + assert.Equal(t, "*Test", typeName2) +} - pkName := GetPackageName(&Test{}) - pkName2 := GetPackageName(Test{}) +func Test_GetFullTypeName(t *testing.T) { + t1 := Test{A: 10} + t2 := &Test{A: 10} - assert.Equal(t, "typeMapper", pkName) - assert.Equal(t, "typeMapper", pkName2) + typeName1 := GetFullTypeName(t1) + typeName2 := GetFullTypeName(t2) - assert.Equal(t, "typeMapper.Test", typeName) + assert.Equal(t, "typeMapper.Test", typeName1) assert.Equal(t, "*typeMapper.Test", typeName2) - assert.Equal(t, "*Test", typeName3) - assert.Equal(t, "Test", typeName4) - - q1.A = 100 - q22.A = 100 - - assert.NotNil(t, d1) - assert.NotNil(t, d2) - assert.NotNil(t, d3) - assert.NotNil(t, c1) - assert.NotNil(t, c2) - assert.NotNil(t, c3) - assert.NotNil(t, q) - assert.NotNil(t, q1) - assert.NotNil(t, q11) - assert.NotNil(t, q2) - assert.NotNil(t, q22) - assert.NotNil(t, q222) - assert.NotNil(t, q3) - assert.NotNil(t, q4) - assert.NotNil(t, r) - assert.NotNil(t, r2) - assert.NotNil(t, y) - assert.NotNil(t, y1) - assert.NotNil(t, y2) - assert.NotNil(t, z) - assert.NotNil(t, z1) - assert.NotNil(t, z2) - assert.NotZero(t, q1.A) - assert.NotZero(t, q22.A) +} + +func Test_InstanceByTypeName(t *testing.T) { + s1 := InstanceByTypeName("typeMapper.Test").(Test) + s1.A = 100 + assert.NotNil(t, s1) + assert.NotZero(t, s1.A) + + s2 := InstanceByTypeName("*typeMapper.Test").(*Test) + s2.A = 100 + assert.NotNil(t, s2) + assert.NotZero(t, s2.A) + + s3 := InstanceByTypeName("*Test").(*Test) + assert.NotNil(t, s3) + + s4 := InstanceByTypeName("Test").(Test) + assert.NotNil(t, s4) +} + +func Test_InstancePointerByTypeName(t *testing.T) { + s1 := InstancePointerByTypeName("*typeMapper.Test").(*Test) + s2 := InstancePointerByTypeName("typeMapper.Test").(*Test) + s3 := InstancePointerByTypeName("*Test").(*Test) + s4 := InstancePointerByTypeName("Test").(*Test) + + assert.NotNil(t, s1) + assert.NotNil(t, s2) + assert.NotNil(t, s3) + assert.NotNil(t, s4) +} + +func Test_GetTypeFromGeneric(t *testing.T) { + s1 := GetTypeFromGeneric[Test]() + s2 := GetTypeFromGeneric[*Test]() + s3 := GetTypeFromGeneric[ITest]() + + assert.NotNil(t, s1) + assert.NotNil(t, s2) + assert.NotNil(t, s3) +} + +func Test_GenericInstanceByT(t *testing.T) { + s1 := GenericInstanceByT[*Test]() + s2 := GenericInstanceByT[Test]() + + assert.NotNil(t, s1) + assert.NotNil(t, s2) +} + +func Test_TypeByNameAndImplementedInterface(t *testing.T) { + s1 := TypeByNameAndImplementedInterface[ITest]("*typeMapper.Test") + + assert.NotNil(t, s1) +} + +func Test_EmptyInstanceByTypeNameAndImplementedInterface(t *testing.T) { + s1 := EmptyInstanceByTypeNameAndImplementedInterface[ITest]("*typeMapper.Test") + + assert.NotNil(t, s1) +} + +func Test_GetReflectType(t *testing.T) { + s1 := GetReflectType(Test{}) + s2 := GetReflectType(&Test{}) + s3 := GetReflectType((*ITest)(nil)) + + assert.NotNil(t, s1) + assert.NotNil(t, s2) + assert.NotNil(t, s3) +} + +func Test_GetPackageName(t *testing.T) { + pkName := GetPackageName(&Test{}) + pkName2 := GetPackageName(Test{}) + + assert.Equal(t, "typemapper", pkName) + assert.Equal(t, "typemapper", pkName2) } type Test struct { diff --git a/internal/pkg/reflection/typemapper/unsafe_types.go b/internal/pkg/reflection/typemapper/unsafe_types.go index b90fbdcf..e4034894 100644 --- a/internal/pkg/reflection/typemapper/unsafe_types.go +++ b/internal/pkg/reflection/typemapper/unsafe_types.go @@ -1,4 +1,4 @@ -package typeMapper +package typemapper import "unsafe" diff --git a/internal/services/catalogwriteservice/internal/products/configurations/mappings/mapping_profile.go b/internal/services/catalogwriteservice/internal/products/configurations/mappings/mapping_profile.go index b3f47b90..41ed2dc7 100644 --- a/internal/services/catalogwriteservice/internal/products/configurations/mappings/mapping_profile.go +++ b/internal/services/catalogwriteservice/internal/products/configurations/mappings/mapping_profile.go @@ -2,7 +2,7 @@ package mappings import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/datamodels" dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" productsService "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/grpc/genproto" @@ -37,7 +37,7 @@ func ConfigureProductsMappings() error { return nil } return &productsService.Product{ - ProductId: product.ProductId.String(), + ProductId: product.Id.String(), Name: product.Name, Description: product.Description, Price: product.Price, diff --git a/internal/services/catalogwriteservice/internal/products/data/models/product_data_model.go b/internal/services/catalogwriteservice/internal/products/data/datamodels/product_data_model.go similarity index 97% rename from internal/services/catalogwriteservice/internal/products/data/models/product_data_model.go rename to internal/services/catalogwriteservice/internal/products/data/datamodels/product_data_model.go index 5b3281c4..8242d06e 100644 --- a/internal/services/catalogwriteservice/internal/products/data/models/product_data_model.go +++ b/internal/services/catalogwriteservice/internal/products/data/datamodels/product_data_model.go @@ -1,4 +1,4 @@ -package models +package datamodels import ( "time" diff --git a/internal/services/catalogwriteservice/internal/products/dtos/v1/product_dto.go b/internal/services/catalogwriteservice/internal/products/dtos/v1/product_dto.go index 051c8b42..9a3a386d 100644 --- a/internal/services/catalogwriteservice/internal/products/dtos/v1/product_dto.go +++ b/internal/services/catalogwriteservice/internal/products/dtos/v1/product_dto.go @@ -7,7 +7,7 @@ import ( ) type ProductDto struct { - ProductId uuid.UUID `json:"productId"` + Id uuid.UUID `json:"id"` Name string `json:"name"` Description string `json:"description"` Price float64 `json:"price"` diff --git a/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product_handler.go b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product_handler.go index d562fcd1..04d02cab 100644 --- a/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product_handler.go +++ b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product_handler.go @@ -8,6 +8,8 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/gormdbcontext" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/datamodels" dtosv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos" @@ -49,7 +51,11 @@ func (c *createProductHandler) Handle( var createProductResult *dtos.CreateProductResponseDto - result, err := c.CatalogsDBContext.AddProduct(ctx, product) + result, err := gormdbcontext.AddModel[*datamodel.ProductDataModel, *models.Product]( + ctx, + c.CatalogsDBContext, + product, + ) if err != nil { return nil, err } diff --git a/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_handler.go b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_handler.go index 716a6a85..840ab444 100644 --- a/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_handler.go +++ b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_handler.go @@ -7,6 +7,8 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/gormdbcontext" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/datamodels" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" integrationEvents "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/events/integrationevents" @@ -40,7 +42,7 @@ func (c *deleteProductHandler) Handle( ctx context.Context, command *DeleteProduct, ) (*mediatr.Unit, error) { - err := c.CatalogsDBContext.DeleteProductByID(ctx, command.ProductID) + err := gormdbcontext.DeleteDataModelByID[*datamodels.ProductDataModel](ctx, c.CatalogsDBContext, command.ProductID) if err != nil { return nil, err } diff --git a/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id_handler.go b/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id_handler.go index ac915b5a..2e913bfc 100644 --- a/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id_handler.go +++ b/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id_handler.go @@ -8,9 +8,12 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/gormdbcontext" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/datamodels" dtoV1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "github.com/mehdihadeli/go-mediatr" ) @@ -37,7 +40,11 @@ func (c *GetProductByIDHandler) Handle( ctx context.Context, query *GetProductById, ) (*dtos.GetProductByIdResponseDto, error) { - product, err := c.CatalogsDBContext.FindProductByID(ctx, query.ProductID) + product, err := gormdbcontext.FindModelByID[*datamodels.ProductDataModel, *models.Product]( + ctx, + c.CatalogsDBContext, + query.ProductID, + ) if err != nil { return nil, err } diff --git a/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/get_products_handler.go b/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/get_products_handler.go index 5c5c2499..62e27ce9 100644 --- a/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/get_products_handler.go +++ b/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/get_products_handler.go @@ -5,9 +5,9 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers/gormextensions" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/datamodels" dtosv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/gettingproducts/v1/dtos" @@ -38,10 +38,10 @@ func (c *getProductsHandler) Handle( ctx context.Context, query *GetProducts, ) (*dtos.GetProductsResponseDto, error) { - products, err := helpers.Paginate[*datamodel.ProductDataModel, *models.Product]( + products, err := gormextensions.Paginate[*datamodel.ProductDataModel, *models.Product]( ctx, query.ListQuery, - c.CatalogsDBContext.DB, + c.CatalogsDBContext.DB(), ) if err != nil { return nil, customErrors.NewApplicationErrorWrap( diff --git a/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_handler.go b/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_handler.go index 0970c9f7..ee63478a 100644 --- a/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_handler.go +++ b/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_handler.go @@ -8,11 +8,11 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers/gormextensions" reflectionHelper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/reflectionhelper" typeMapper "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" - datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/datamodels" dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/dtos" @@ -81,7 +81,7 @@ func (c *searchProductsHandler) prepareSearchDBQuery( typeMapper.GetTypeFromGeneric[*datamodel.ProductDataModel](), ) - dbQuery := c.CatalogsDBContext.DB + dbQuery := c.CatalogsDBContext.DB() for _, field := range fields { if field.Type.Kind() != reflect.String { diff --git a/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_handler.go b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_handler.go index b10819c1..20ff42e7 100644 --- a/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_handler.go +++ b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_handler.go @@ -9,9 +9,12 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/gormdbcontext" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/datamodels" dto "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/events/integrationevents" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "github.com/mehdihadeli/go-mediatr" ) @@ -44,7 +47,11 @@ func (c *updateProductHandler) Handle( ctx context.Context, command *UpdateProduct, ) (*mediatr.Unit, error) { - product, err := c.CatalogsDBContext.FindProductByID(ctx, command.ProductID) + product, err := gormdbcontext.FindModelByID[*datamodels.ProductDataModel, *models.Product]( + ctx, + c.CatalogsDBContext, + command.ProductID, + ) if err != nil { return nil, customErrors.NewApplicationErrorWrapWithCode( err, @@ -61,7 +68,11 @@ func (c *updateProductHandler) Handle( product.Description = command.Description product.UpdatedAt = command.UpdatedAt - updatedProduct, err := c.CatalogsDBContext.UpdateProduct(ctx, product) + updatedProduct, err := gormdbcontext.UpdateModel[*datamodels.ProductDataModel, *models.Product]( + ctx, + c.CatalogsDBContext, + product, + ) if err != nil { return nil, customErrors.NewApplicationErrorWrap( err, diff --git a/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator_seed.go b/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator_seed.go index fec85dc7..7fc9797d 100644 --- a/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator_seed.go +++ b/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/catalogs_configurator_seed.go @@ -4,7 +4,7 @@ import ( "time" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/testfixture" - datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/datamodels" "emperror.dev/errors" "github.com/brianvoe/gofakeit/v6" diff --git a/internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext.go b/internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext.go index 9b261b02..8417e43e 100644 --- a/internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext.go +++ b/internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext.go @@ -2,257 +2,23 @@ package dbcontext import ( "context" - "fmt" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/scopes" - datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/gormdbcontext" - uuid "github.com/satori/go.uuid" "gorm.io/gorm" ) type CatalogContextActionFunc func(ctx context.Context, catalogContext *CatalogsGormDBContext) error type CatalogsGormDBContext struct { - *gorm.DB - logger logger.Logger + // our dbcontext base + contracts.IGormDBContext } -func NewCatalogsDBContext( - db *gorm.DB, - log logger.Logger, -) *CatalogsGormDBContext { - c := &CatalogsGormDBContext{DB: db, logger: log} +func NewCatalogsDBContext(db *gorm.DB) *CatalogsGormDBContext { + // initialize base + c := &CatalogsGormDBContext{IGormDBContext: gormdbcontext.NewGormDBContext(db)} return c } - -// WithTx creates a transactional DBContext with getting tx-gorm from the ctx. This will throw an error if the transaction does not exist. -func (c *CatalogsGormDBContext) WithTx( - ctx context.Context, -) (*CatalogsGormDBContext, error) { - tx, err := helpers.GetTxFromContext(ctx) - if err != nil { - return nil, err - } - - return NewCatalogsDBContext(tx, c.logger), nil -} - -// WithTxIfExists creates a transactional DBContext with getting tx-gorm from the ctx. not throw an error if the transaction is not existing and returns an existing database. -func (c *CatalogsGormDBContext) WithTxIfExists( - ctx context.Context, -) *CatalogsGormDBContext { - tx := helpers.GetTxFromContextIfExists(ctx) - if tx == nil { - return c - } - - return NewCatalogsDBContext(tx, c.logger) -} - -func (c *CatalogsGormDBContext) RunInTx( - ctx context.Context, - action CatalogContextActionFunc, -) error { - // https://gorm.io/docs/transactions.html#Transaction - tx := c.WithContext(ctx).Begin() - - c.logger.Info("beginning database transaction") - - gormContext := helpers.SetTxToContext(ctx, tx) - ctx = gormContext - - defer func() { - if r := recover(); r != nil { - tx.WithContext(ctx).Rollback() - - if err, _ := r.(error); err != nil { - c.logger.Errorf( - "panic tn the transaction, rolling back transaction with panic err: %+v", - err, - ) - } else { - c.logger.Errorf("panic tn the transaction, rolling back transaction with panic message: %+v", r) - } - } - }() - - err := action(ctx, c) - if err != nil { - c.logger.Error("rolling back transaction") - tx.WithContext(ctx).Rollback() - - return err - } - - c.logger.Info("committing transaction") - - if err = tx.WithContext(ctx).Commit().Error; err != nil { - c.logger.Errorf("transaction commit error: ", err) - } - - return err -} - -// Extensions for shared and reusable methods. for complex and none-reusable queries we use DBContext directly - -func (c *CatalogsGormDBContext) ExistsProduct( - ctx context.Context, - id uuid.UUID, -) bool { - var count int64 - - c.WithContext(ctx).Model(&datamodel.ProductDataModel{}).Scopes(scopes.FilterByID(id)).Count(&count) - - return count > 0 -} - -func (c *CatalogsGormDBContext) FindProductByID( - ctx context.Context, - id uuid.UUID, -) (*models.Product, error) { - var productData *datamodel.ProductDataModel - - // https://gorm.io/docs/query.html#Retrieving-objects-with-primary-key - // https://gorm.io/docs/query.html#Struct-amp-Map-Conditions - // https://gorm.io/docs/query.html#Inline-Condition - // https://gorm.io/docs/advanced_query.html - // result := c.WithContext(ctx).First(&productData, "id = ?", id) - // result := c.WithContext(ctx).First(&datamodel.ProductDataModel{Id: id}) - // result := c.WithContext(ctx).Scopes(scopes.FilterByID(id)).First(&productData) - result := c.WithContext(ctx).First(&productData, id) - if result.Error != nil { - return nil, customErrors.NewNotFoundErrorWrap( - result.Error, - fmt.Sprintf( - "product with id `%s` not found in the database", - id.String(), - ), - ) - } - - c.logger.Infof("Number of affected rows are: %d", result.RowsAffected) - - product, err := mapper.Map[*models.Product](productData) - if err != nil { - return nil, customErrors.NewInternalServerErrorWrap( - err, - "error in the mapping Product", - ) - } - - return product, nil -} - -// DeleteProductByID delete the product inner a tx if exists -func (c *CatalogsGormDBContext) DeleteProductByID( - ctx context.Context, - id uuid.UUID, -) error { - dbContext := c.WithTxIfExists(ctx) - - exists := c.ExistsProduct(ctx, id) - if !exists { - return customErrors.NewNotFoundError(fmt.Sprintf("product with id `%s` not found in the database", - id.String(), - )) - } - - // https://gorm.io/docs/delete.html#Delete-a-Record - // https://gorm.io/docs/delete.html#Find-soft-deleted-records - // result := dbContext.WithContext(ctx).Delete(&datamodel.ProductDataModel{Id: id}) - result := dbContext.WithContext(ctx).Delete(&datamodel.ProductDataModel{}, id) - if result.Error != nil { - return customErrors.NewInternalServerErrorWrap( - result.Error, - fmt.Sprintf( - "error in deleting product with id `%s` in the database", - id.String(), - ), - ) - } - - c.logger.Infof("Number of affected rows are: %d", result.RowsAffected) - - return nil -} - -// AddProduct add the product inner a tx if exists -func (c *CatalogsGormDBContext) AddProduct( - ctx context.Context, - product *models.Product, -) (*models.Product, error) { - dbContext := c.WithTxIfExists(ctx) - - productDataModel, err := mapper.Map[*datamodel.ProductDataModel](product) - if err != nil { - return nil, customErrors.NewInternalServerErrorWrap( - err, - "error in the mapping ProductDataModel", - ) - } - - // https://gorm.io/docs/create.html - result := dbContext.WithContext(ctx).Create(productDataModel) - if result.Error != nil { - return nil, customErrors.NewConflictErrorWrap( - result.Error, - "product already exists", - ) - } - - c.logger.Infof("Number of affected rows are: %d", result.RowsAffected) - - product, err = mapper.Map[*models.Product](productDataModel) - if err != nil { - return nil, customErrors.NewInternalServerErrorWrap( - err, - "error in the mapping Product", - ) - } - - return product, err -} - -// UpdateProduct update the product inner a tx if exists -func (c *CatalogsGormDBContext) UpdateProduct( - ctx context.Context, - product *models.Product, -) (*models.Product, error) { - dbContext := c.WithTxIfExists(ctx) - - productDataModel, err := mapper.Map[*datamodel.ProductDataModel](product) - if err != nil { - return nil, customErrors.NewInternalServerErrorWrap( - err, - "error in the mapping ProductDataModel", - ) - } - - // https://gorm.io/docs/update.html - result := dbContext.WithContext(ctx).Updates(productDataModel) - if result.Error != nil { - return nil, customErrors.NewInternalServerErrorWrap( - result.Error, - "error in updating the product", - ) - } - - c.logger.Infof("Number of affected rows are: %d", result.RowsAffected) - - product, err = mapper.Map[*models.Product](productDataModel) - if err != nil { - return nil, customErrors.NewInternalServerErrorWrap( - err, - "error in the mapping Product", - ) - } - - return product, err -} diff --git a/internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext_test.go b/internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext_test.go index 58509af2..dcb5ab58 100644 --- a/internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext_test.go +++ b/internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext_test.go @@ -15,9 +15,10 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/zap" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/gormdbcontext" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/scopes" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations/mappings" - datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/datamodels" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "emperror.dev/errors" @@ -49,8 +50,9 @@ func (s *DBContextTestSuite) Test_FindProductByID() { id := s.items[0].Id - p, err := s.dbContext.FindProductByID( + p, err := gormdbcontext.FindModelByID[*datamodel.ProductDataModel, *models.Product]( context.Background(), + s.dbContext, id, ) s.Require().NoError(err) @@ -64,8 +66,9 @@ func (s *DBContextTestSuite) Test_ExistsProductByID() { id := s.items[0].Id - exist := s.dbContext.ExistsProduct( + exist := gormdbcontext.Exists[*datamodel.ProductDataModel]( context.Background(), + s.dbContext, id, ) s.Require().True(exist) @@ -76,10 +79,12 @@ func (s *DBContextTestSuite) Test_NoneExistsProductByID() { id := uuid.NewV4() - exist := s.dbContext.ExistsProduct( + exist := gormdbcontext.Exists[*datamodel.ProductDataModel]( context.Background(), + s.dbContext, id, ) + s.Require().False(exist) } @@ -88,14 +93,16 @@ func (s *DBContextTestSuite) Test_DeleteProductByID() { id := s.items[0].Id - err := s.dbContext.DeleteProductByID( + err := gormdbcontext.DeleteDataModelByID[*datamodel.ProductDataModel]( context.Background(), + s.dbContext, id, ) s.Require().NoError(err) - p, err := s.dbContext.FindProductByID( + p, err := gormdbcontext.FindModelByID[*datamodel.ProductDataModel, *models.Product]( context.Background(), + s.dbContext, id, ) s.Require().Error(err) @@ -103,17 +110,17 @@ func (s *DBContextTestSuite) Test_DeleteProductByID() { // https://gorm.io/docs/delete.html#Find-soft-deleted-records var softDeletedProduct *datamodel.ProductDataModel - s.dbContext.Scopes(scopes.FilterAllItemsWithSoftDeleted).First(&softDeletedProduct, id) + s.dbContext.DB().Scopes(scopes.FilterAllItemsWithSoftDeleted).First(&softDeletedProduct, id) s.Require().NotNil(softDeletedProduct) var deletedCount int64 var allCount int64 // https://gorm.io/docs/advanced_query.html#Count - s.dbContext.Model(&datamodel.ProductDataModel{}).Scopes(scopes.FilterAllItemsWithSoftDeleted).Count(&allCount) + s.dbContext.DB().Model(&datamodel.ProductDataModel{}).Scopes(scopes.FilterAllItemsWithSoftDeleted).Count(&allCount) s.Equal(allCount, int64(2)) - s.dbContext.Model(&datamodel.ProductDataModel{}).Scopes(scopes.SoftDeleted).Count(&deletedCount) + s.dbContext.DB().Model(&datamodel.ProductDataModel{}).Scopes(scopes.SoftDeleted).Count(&deletedCount) s.Equal(deletedCount, int64(1)) } @@ -127,11 +134,16 @@ func (s *DBContextTestSuite) Test_CreateProduct() { Price: gofakeit.Price(100, 1000), } - res, err := s.dbContext.AddProduct(context.Background(), item) + res, err := gormdbcontext.AddModel[*datamodel.ProductDataModel, *models.Product]( + context.Background(), + s.dbContext, + item, + ) s.Require().NoError(err) - p, err := s.dbContext.FindProductByID( + p, err := gormdbcontext.FindModelByID[*datamodel.ProductDataModel, *models.Product]( context.Background(), + s.dbContext, item.Id, ) s.Require().NoError(err) @@ -146,8 +158,9 @@ func (s *DBContextTestSuite) Test_UpdateProduct() { id := s.items[0].Id - p, err := s.dbContext.FindProductByID( + p, err := gormdbcontext.FindModelByID[*datamodel.ProductDataModel, *models.Product]( context.Background(), + s.dbContext, id, ) s.Require().NoError(err) @@ -156,11 +169,16 @@ func (s *DBContextTestSuite) Test_UpdateProduct() { item := p item.Name = newName - res, err := s.dbContext.UpdateProduct(context.Background(), item) + res, err := gormdbcontext.UpdateModel[*datamodel.ProductDataModel, *models.Product]( + context.Background(), + s.dbContext, + item, + ) s.Require().NoError(err) - p2, err := s.dbContext.FindProductByID( + p2, err := gormdbcontext.FindModelByID[*datamodel.ProductDataModel, *models.Product]( context.Background(), + s.dbContext, id, ) s.Require().NoError(err) @@ -209,20 +227,22 @@ func (s *DBContextTestSuite) TearDownTest() { s.Require().NoError(err) mapper.ClearMappings() + + s.app.RequireStop() } func (s *DBContextTestSuite) initDB() { - err := migrateGorm(s.dbContext.DB) + err := migrateGorm(s.dbContext.DB()) s.Require().NoError(err) - products, err := seedData(s.dbContext.DB) + products, err := seedData(s.dbContext.DB()) s.Require().NoError(err) s.items = products } func (s *DBContextTestSuite) cleanupDB() error { - sqldb, _ := s.dbContext.DB.DB() + sqldb, _ := s.dbContext.DB().DB() e := sqldb.Close() s.Require().NoError(e) @@ -259,7 +279,6 @@ func seedData(gormDB *gorm.DB) ([]*datamodel.ProductDataModel, error) { }, } - // migration will do in app configuration // seed data err := gormDB.CreateInBatches(products, len(products)).Error if err != nil { diff --git a/internal/services/catalogwriteservice/internal/shared/testfixtures/integration/integration_test_fixture.go b/internal/services/catalogwriteservice/internal/shared/testfixtures/integration/integration_test_fixture.go index 4bf67f8c..b68cf4b7 100644 --- a/internal/services/catalogwriteservice/internal/shared/testfixtures/integration/integration_test_fixture.go +++ b/internal/services/catalogwriteservice/internal/shared/testfixtures/integration/integration_test_fixture.go @@ -8,12 +8,12 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/bus" fxcontracts "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/fxapp/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" - gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" + gormPostgres "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers/gormextensions" config2 "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/rabbitmq/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/testfixture" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/config" - datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/datamodels" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/app/test" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/data/dbcontext" productsService "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/grpc/genproto" diff --git a/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest/unit_test_fixture.go b/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest/unit_test_fixture.go index 17ec3d71..03b4889f 100644 --- a/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest/unit_test_fixture.go +++ b/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest/unit_test_fixture.go @@ -13,10 +13,10 @@ import ( defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/external/gromlog" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers/gormextensions" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/configurations/mappings" - datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/datamodels" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/data/dbcontext" "emperror.dev/errors" @@ -64,11 +64,11 @@ func NewUnitTestSharedFixture(t *testing.T) *UnitTestSharedFixture { func (c *UnitTestSharedFixture) BeginTx() { c.Log.Info("starting transaction") // seems when we `Begin` a transaction on gorm.DB (with SQLLite in-memory) our previous gormDB before transaction will remove and the new gormDB with tx will go on the memory - tx := c.CatalogDBContext.Begin() - gormContext := helpers.SetTxToContext(c.Ctx, tx) + tx := c.CatalogDBContext.DB().Begin() + gormContext := gormextensions.SetTxToContext(c.Ctx, tx) c.Ctx = gormContext - //// works on both transaction and none-transactional dbcontext + //// works on both transaction and none-transactional gormdbcontext //var productData []*datamodel.ProductDataModel //var productData2 []*datamodel.ProductDataModel // @@ -77,7 +77,7 @@ func (c *UnitTestSharedFixture) BeginTx() { } func (c *UnitTestSharedFixture) CommitTx() { - tx := helpers.GetTxFromContextIfExists(c.Ctx) + tx := gormextensions.GetTxFromContextIfExists(c.Ctx) if tx != nil { c.Log.Info("committing transaction") tx.Commit() @@ -132,6 +132,22 @@ func (c *UnitTestSharedFixture) setupDB() { c.initDB(dbContext) } +func (c *UnitTestSharedFixture) createSQLLiteDBContext() *dbcontext.CatalogsGormDBContext { + // https://gorm.io/docs/connecting_to_the_database.html#SQLite + // https://github.com/glebarez/sqlite + // https://www.connectionstrings.com/sqlite/ + gormSQLLiteDB, err := gorm.Open( + sqlite.Open(c.dbFilePath), + &gorm.Config{ + Logger: gromlog.NewGormCustomLogger(defaultLogger.GetLogger()), + }) + c.Require().NoError(err) + + dbContext := dbcontext.NewCatalogsDBContext(gormSQLLiteDB) + + return dbContext +} + func (c *UnitTestSharedFixture) initDB(dbContext *dbcontext.CatalogsGormDBContext) { // migrations for our database err := migrateGorm(dbContext) @@ -145,7 +161,7 @@ func (c *UnitTestSharedFixture) initDB(dbContext *dbcontext.CatalogsGormDBContex } func (c *UnitTestSharedFixture) cleanupDB() error { - sqldb, _ := c.CatalogDBContext.DB.DB() + sqldb, _ := c.CatalogDBContext.DB().DB() e := sqldb.Close() c.Require().NoError(e) @@ -155,24 +171,8 @@ func (c *UnitTestSharedFixture) cleanupDB() error { return err } -func (c *UnitTestSharedFixture) createSQLLiteDBContext() *dbcontext.CatalogsGormDBContext { - // https://gorm.io/docs/connecting_to_the_database.html#SQLite - // https://github.com/glebarez/sqlite - // https://www.connectionstrings.com/sqlite/ - gormSQLLiteDB, err := gorm.Open( - sqlite.Open(c.dbFilePath), - &gorm.Config{ - Logger: gromlog.NewGormCustomLogger(defaultLogger.GetLogger()), - }) - c.Require().NoError(err) - - dbContext := dbcontext.NewCatalogsDBContext(gormSQLLiteDB, c.Log) - - return dbContext -} - func migrateGorm(dbContext *dbcontext.CatalogsGormDBContext) error { - err := dbContext.DB.AutoMigrate(&datamodel.ProductDataModel{}) + err := dbContext.DB().AutoMigrate(&datamodel.ProductDataModel{}) if err != nil { return err } @@ -201,7 +201,7 @@ func seedDataManually( } // seed data - err := dbContext.DB.CreateInBatches(products, len(products)).Error + err := dbContext.DB().CreateInBatches(products, len(products)).Error if err != nil { return nil, errors.Wrap(err, "error in seed database") } diff --git a/internal/services/catalogwriteservice/test/integration/products/features/gettingproductbyid/v1/get_product_by_id_test.go b/internal/services/catalogwriteservice/test/integration/products/features/gettingproductbyid/v1/get_product_by_id_test.go index b92e0ceb..daeb872e 100644 --- a/internal/services/catalogwriteservice/test/integration/products/features/gettingproductbyid/v1/get_product_by_id_test.go +++ b/internal/services/catalogwriteservice/test/integration/products/features/gettingproductbyid/v1/get_product_by_id_test.go @@ -106,7 +106,7 @@ var _ = Describe("Get Product by ID Feature", func() { "Should return a product with the correct ID", func() { Expect(result.Product).NotTo(BeNil()) - Expect(result.Product.ProductId).To(Equal(id)) + Expect(result.Product.Id).To(Equal(id)) }, ) }, diff --git a/internal/services/catalogwriteservice/test/integration/products/features/updatingproduct/v1/update_product_test.go b/internal/services/catalogwriteservice/test/integration/products/features/updatingproduct/v1/update_product_test.go index c3fd60db..9dcc1c0a 100644 --- a/internal/services/catalogwriteservice/test/integration/products/features/updatingproduct/v1/update_product_test.go +++ b/internal/services/catalogwriteservice/test/integration/products/features/updatingproduct/v1/update_product_test.go @@ -13,7 +13,7 @@ import ( customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/hypothesis" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/test/messaging" - datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/models" + datamodel "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/datamodels" v1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/events/integrationevents" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/integration" diff --git a/internal/services/catalogwriteservice/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go b/internal/services/catalogwriteservice/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go index af38d30e..7bdb8fe0 100644 --- a/internal/services/catalogwriteservice/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go +++ b/internal/services/catalogwriteservice/test/unit/products/features/creatingproduct/v1/create_product_handler_unit_test.go @@ -10,9 +10,12 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/mapper" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/gormdbcontext" + datamodels "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/datamodels" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" creatingproductv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1" creatingproductdtosv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/dtos" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/models" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" "emperror.dev/errors" @@ -71,7 +74,11 @@ func (c *createProductHandlerUnitTests) Test_Handle_Should_Create_New_Product_Wi c.Bus.AssertNumberOfCalls(c.T(), "PublishMessage", 1) - res, err := c.CatalogDBContext.FindProductByID(c.Ctx, id) + res, err := gormdbcontext.FindModelByID[*datamodels.ProductDataModel, *models.Product]( + c.Ctx, + c.CatalogDBContext, + id, + ) c.Require().NoError(err) c.Assert().Equal(res.Id, id) diff --git a/internal/services/catalogwriteservice/test/unit/products/features/deletingproduct/v1/delete_product_handler_unit_test.go b/internal/services/catalogwriteservice/test/unit/products/features/deletingproduct/v1/delete_product_handler_unit_test.go index ad12a250..3d24aec7 100644 --- a/internal/services/catalogwriteservice/test/unit/products/features/deletingproduct/v1/delete_product_handler_unit_test.go +++ b/internal/services/catalogwriteservice/test/unit/products/features/deletingproduct/v1/delete_product_handler_unit_test.go @@ -9,6 +9,8 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/gormdbcontext" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/datamodels" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" deletingproductv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" @@ -65,7 +67,7 @@ func (c *deleteProductHandlerUnitTests) Test_Handle_Should_Delete_Product_With_V c.Require().NoError(err) - p, err := c.CatalogDBContext.FindProductByID(c.Ctx, id) + p, err := gormdbcontext.FindDataModelByID[*datamodels.ProductDataModel](c.Ctx, c.CatalogDBContext, id) c.Require().Nil(p) c.Require().Error(err) diff --git a/internal/services/catalogwriteservice/test/unit/products/features/gettingproductbyid/v1/get_product_by_id_handler_unit_test.go b/internal/services/catalogwriteservice/test/unit/products/features/gettingproductbyid/v1/get_product_by_id_handler_unit_test.go index 24912f25..0add2d03 100644 --- a/internal/services/catalogwriteservice/test/unit/products/features/gettingproductbyid/v1/get_product_by_id_handler_unit_test.go +++ b/internal/services/catalogwriteservice/test/unit/products/features/gettingproductbyid/v1/get_product_by_id_handler_unit_test.go @@ -57,7 +57,7 @@ func (c *getProductByIdHandlerTest) Test_Handle_Should_Return_Correct_Product_By c.Require().NoError(err) c.Assert().NotNil(dto) c.Assert().NotNil(dto.Product) - c.Assert().Equal(dto.Product.ProductId, product.Id) + c.Assert().Equal(dto.Product.Id, product.Id) c.Assert().Equal(dto.Product.Name, product.Name) } @@ -73,7 +73,7 @@ func (c *getProductByIdHandlerTest) Test_Handle_Should_Return_NotFound_Error_For c.ErrorContains( err, fmt.Sprintf( - "product with id `%s` not found in the database", + "product_data_model with id `%s` not found in the database", id.String(), ), ) @@ -93,5 +93,5 @@ func (c *getProductByIdHandlerTest) Test_Handle_Should_Return_Error_For_Error_In c.Nil(dto) c.Require().Error(err) c.True(customErrors.IsInternalServerError(err)) - c.ErrorContains(err, "error in the mapping Product") + c.ErrorContains(err, "error in the mapping product") } diff --git a/internal/services/catalogwriteservice/test/unit/products/features/updatingproduct/v1/update_product_handler_unit_test.go b/internal/services/catalogwriteservice/test/unit/products/features/updatingproduct/v1/update_product_handler_unit_test.go index 961fd945..a2535fdc 100644 --- a/internal/services/catalogwriteservice/test/unit/products/features/updatingproduct/v1/update_product_handler_unit_test.go +++ b/internal/services/catalogwriteservice/test/unit/products/features/updatingproduct/v1/update_product_handler_unit_test.go @@ -10,6 +10,8 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/gormdbcontext" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/data/datamodels" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/dtos/v1/fxparams" updatingoroductsv1 "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" @@ -71,8 +73,9 @@ func (c *updateProductHandlerUnitTests) Test_Handle_Should_Update_Product_With_V c.Require().NoError(err) - updatedProduct, err := c.CatalogDBContext.FindProductByID( + updatedProduct, err := gormdbcontext.FindDataModelByID[*datamodels.ProductDataModel]( c.Ctx, + c.CatalogDBContext, updateProductCommand.ProductID, ) c.Require().NoError(err) diff --git a/internal/services/catalogwriteservice/test/unit/products/mappings_profile_test.go b/internal/services/catalogwriteservice/test/unit/products/mappings_profile_test.go index f675268b..651ee4a8 100644 --- a/internal/services/catalogwriteservice/test/unit/products/mappings_profile_test.go +++ b/internal/services/catalogwriteservice/test/unit/products/mappings_profile_test.go @@ -38,7 +38,7 @@ func (m *mappingProfileUnitTests) Test_Mappings() { } productDto := &dtoV1.ProductDto{ - ProductId: uuid.NewV4(), + Id: uuid.NewV4(), Name: gofakeit.Name(), CreatedAt: time.Now(), Description: gofakeit.EmojiDescription(), @@ -48,7 +48,7 @@ func (m *mappingProfileUnitTests) Test_Mappings() { m.Run("Should_Map_Product_To_ProductDto", func() { d, err := mapper.Map[*dtoV1.ProductDto](productModel) m.Require().NoError(err) - m.Equal(productModel.Id, d.ProductId) + m.Equal(productModel.Id, d.Id) m.Equal(productModel.Name, d.Name) }) @@ -61,7 +61,7 @@ func (m *mappingProfileUnitTests) Test_Mappings() { m.Run("Should_Map_ProductDto_To_Product", func() { d, err := mapper.Map[*models.Product](productDto) m.Require().NoError(err) - m.Equal(productDto.ProductId, d.Id) + m.Equal(productDto.Id, d.Id) m.Equal(productDto.Name, d.Name) }) From 5ff36d2f4a3565f8557bddadc49c48ea2505fd4c Mon Sep 17 00:00:00 2001 From: Mehdi Hadeli Date: Tue, 19 Dec 2023 01:09:37 +0330 Subject: [PATCH 13/15] feat: :sparkles: add validation pipeline for mediatr #92 --- .../pipeline/validation_pipeline.go | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 internal/pkg/validation/pipeline/validation_pipeline.go diff --git a/internal/pkg/validation/pipeline/validation_pipeline.go b/internal/pkg/validation/pipeline/validation_pipeline.go new file mode 100644 index 00000000..5ea3d440 --- /dev/null +++ b/internal/pkg/validation/pipeline/validation_pipeline.go @@ -0,0 +1,37 @@ +package pipeline + +import ( + "context" + + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/validation" + + "github.com/mehdihadeli/go-mediatr" +) + +type mediatorValidationPipeline struct { + logger logger.Logger +} + +func NewMediatorValidationPipeline(l logger.Logger) mediatr.PipelineBehavior { + return &mediatorValidationPipeline{logger: l} +} + +func (m mediatorValidationPipeline) Handle( + ctx context.Context, + request interface{}, + next mediatr.RequestHandlerFunc, +) (interface{}, error) { + v, ok := request.(validation.Validator) + if ok { + err := v.Validate() + if err != nil { + validationErr := customErrors.NewValidationErrorWrap(err, "validation failed") + + return nil, validationErr + } + } + + return next(ctx) +} From 03a94a749a68d6e946b9f9bf86507f68b050fbc7 Mon Sep 17 00:00:00 2001 From: Mehdi Hadeli Date: Sun, 7 Jan 2024 22:55:22 +0330 Subject: [PATCH 14/15] refactor: :recycle: some refactoring in cqrs --- internal/pkg/core/cqrs/command.go | 28 ++ internal/pkg/core/cqrs/command_handler.go | 15 + internal/pkg/core/cqrs/command_test.go | 44 +++ internal/pkg/core/cqrs/internal_command.go | 25 ++ .../pkg/core/cqrs/internal_command_test.go | 1 + internal/pkg/core/cqrs/query.go | 25 ++ internal/pkg/core/cqrs/query_handler.go | 9 + internal/pkg/core/cqrs/query_test.go | 38 ++ internal/pkg/core/cqrs/type_info.go | 39 ++ .../otel/tracing/consumer/consumer.go | 2 +- .../otel/tracing/producer/producer.go | 2 +- ...vice.go => message_persistence_service.go} | 8 +- .../serializer/json/json_serilizer_test.go | 6 +- internal/pkg/elasticsearch/elastic_options.go | 2 +- .../config/eventstoredb_options.go | 2 +- internal/pkg/grpc/config/grpc_options.go | 4 +- .../customecho/config/echo_http_options.go | 4 +- .../http/httperrors/customerrors/api_error.go | 48 ++- .../customerrors/application_error.go | 76 ++-- .../customerrors/bad_request_error.go | 49 ++- .../httperrors/customerrors/conflict_error.go | 49 ++- .../httperrors/customerrors/custom_errors.go | 30 +- .../customerrors/custom_errors_test.go | 371 +++++++++++++----- .../httperrors/customerrors/domain_error.go | 65 +-- .../httperrors/customerrors/forbiden_error.go | 49 ++- .../customerrors/internal_server_error.go | 51 ++- .../customerrors/marshaling_error.go | 61 ++- .../customerrors/not_found_error.go | 49 ++- .../customerrors/unauthorized_error.go | 49 ++- .../customerrors/unmarshaling_error.go | 60 ++- .../customerrors/validation_error.go | 60 ++- .../problemdetails/problem_details.go | 2 +- internal/pkg/logger/config/log_options.go | 2 +- internal/pkg/migration/migration_options.go | 2 +- internal/pkg/mongodb/mongo_options.go | 2 +- .../repository/mongo_generic_repository.go | 36 +- .../pipeline/messaging_metrics_pipeline.go | 2 +- internal/pkg/otel/metrics/metrics_options.go | 2 +- internal/pkg/otel/tracing/tracing_options.go | 2 +- .../postgresgorm/contracts/gorm_dbcontext.go | 8 +- internal/pkg/postgresgorm/gorm_options.go | 2 +- .../gormdbcontext/gorm_dbcontext.go | 6 +- .../gorm_dbcontext_extensions.go | 36 +- .../gormdbcontext/gorm_dbcontext_test.go | 4 +- .../mediator_transaction_pipeline.go | 2 +- .../repository/gorm_generic_repository.go | 26 +- .../message_persistence_dbcontext.go | 37 +- .../postgres_message_service.go | 35 +- .../postgres_message_service_test.go | 48 +-- .../pkg/postgrespgx/postgres_pgx_options.go | 2 +- .../pkg/postgressqlx/postgres_sqlx_options.go | 2 +- .../pkg/rabbitmq/config/rabbitmq_options.go | 2 +- internal/pkg/redis/redis_options.go | 2 +- .../reflection_helper_test.go | 14 +- .../pkg/reflection/typemapper/type_mapper.go | 33 +- .../reflection/typemapper/type_mapper_test.go | 38 +- internal/pkg/utils/errorutils/errors.go | 2 +- .../pipeline/validation_pipeline.go | 5 +- .../infrastructure_configurator.go | 2 +- .../catalogwriteservice/config/app_options.go | 2 +- .../creatingproduct/v1/create_product.go | 32 +- .../v1/create_product_endpoint.go | 9 +- .../deletingproduct/v1/delete_product.go | 32 +- .../v1/delete_product_endpoint.go | 9 +- .../v1/get_product_by_id.go | 29 +- .../v1/get_product_by_id_endpoint.go | 9 +- .../searchingproduct/v1/search_products.go | 25 +- .../v1/search_products_endpoint.go | 9 +- .../v1/search_products_handler.go | 2 +- .../updatingproduct/v1/update_product.go | 41 +- .../v1/update_product_endpoint.go | 9 +- .../infrastructure_configurator.go | 4 +- .../data/dbcontext/catalogs_dbcontext.go | 10 +- .../shared/grpc/genproto/products.pb.go | 7 +- .../pg_product_repository_integration_test.go | 4 +- .../updatingproduct/v1/update_product_test.go | 6 +- .../v1/create_product_unit_test.go | 21 +- .../grpc/order_grpc_service_server_test.go | 2 +- 78 files changed, 1288 insertions(+), 651 deletions(-) create mode 100644 internal/pkg/core/cqrs/command.go create mode 100644 internal/pkg/core/cqrs/command_handler.go create mode 100644 internal/pkg/core/cqrs/command_test.go create mode 100644 internal/pkg/core/cqrs/internal_command.go create mode 100644 internal/pkg/core/cqrs/internal_command_test.go create mode 100644 internal/pkg/core/cqrs/query.go create mode 100644 internal/pkg/core/cqrs/query_handler.go create mode 100644 internal/pkg/core/cqrs/query_test.go create mode 100644 internal/pkg/core/cqrs/type_info.go rename internal/pkg/core/messaging/persistmessage/{message_service.go => message_persistence_service.go} (84%) rename internal/pkg/postgresgorm/{mediatr => }/pipelines/mediator_transaction_pipeline.go (98%) diff --git a/internal/pkg/core/cqrs/command.go b/internal/pkg/core/cqrs/command.go new file mode 100644 index 00000000..a7509554 --- /dev/null +++ b/internal/pkg/core/cqrs/command.go @@ -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 +} diff --git a/internal/pkg/core/cqrs/command_handler.go b/internal/pkg/core/cqrs/command_handler.go new file mode 100644 index 00000000..d0b815e1 --- /dev/null +++ b/internal/pkg/core/cqrs/command_handler.go @@ -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) +} diff --git a/internal/pkg/core/cqrs/command_test.go b/internal/pkg/core/cqrs/command_test.go new file mode 100644 index 00000000..30897b8d --- /dev/null +++ b/internal/pkg/core/cqrs/command_test.go @@ -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 +} diff --git a/internal/pkg/core/cqrs/internal_command.go b/internal/pkg/core/cqrs/internal_command.go new file mode 100644 index 00000000..adaf32ee --- /dev/null +++ b/internal/pkg/core/cqrs/internal_command.go @@ -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 +} diff --git a/internal/pkg/core/cqrs/internal_command_test.go b/internal/pkg/core/cqrs/internal_command_test.go new file mode 100644 index 00000000..e9729f96 --- /dev/null +++ b/internal/pkg/core/cqrs/internal_command_test.go @@ -0,0 +1 @@ +package cqrs diff --git a/internal/pkg/core/cqrs/query.go b/internal/pkg/core/cqrs/query.go new file mode 100644 index 00000000..e34d33dc --- /dev/null +++ b/internal/pkg/core/cqrs/query.go @@ -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 +} diff --git a/internal/pkg/core/cqrs/query_handler.go b/internal/pkg/core/cqrs/query_handler.go new file mode 100644 index 00000000..818c423e --- /dev/null +++ b/internal/pkg/core/cqrs/query_handler.go @@ -0,0 +1,9 @@ +package cqrs + +import ( + "context" +) + +type QueryHandler[TQuery Query, TResponse any] interface { + Handle(ctx context.Context, query TQuery) (TResponse, error) +} diff --git a/internal/pkg/core/cqrs/query_test.go b/internal/pkg/core/cqrs/query_test.go new file mode 100644 index 00000000..d37e30c3 --- /dev/null +++ b/internal/pkg/core/cqrs/query_test.go @@ -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 +} diff --git a/internal/pkg/core/cqrs/type_info.go b/internal/pkg/core/cqrs/type_info.go new file mode 100644 index 00000000..273aa7cc --- /dev/null +++ b/internal/pkg/core/cqrs/type_info.go @@ -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 +} diff --git a/internal/pkg/core/messaging/otel/tracing/consumer/consumer.go b/internal/pkg/core/messaging/otel/tracing/consumer/consumer.go index f41a2eda..a82fc5c8 100644 --- a/internal/pkg/core/messaging/otel/tracing/consumer/consumer.go +++ b/internal/pkg/core/messaging/otel/tracing/consumer/consumer.go @@ -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"), diff --git a/internal/pkg/core/messaging/otel/tracing/producer/producer.go b/internal/pkg/core/messaging/otel/tracing/producer/producer.go index 81315286..7dc50a07 100644 --- a/internal/pkg/core/messaging/otel/tracing/producer/producer.go +++ b/internal/pkg/core/messaging/otel/tracing/producer/producer.go @@ -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"), diff --git a/internal/pkg/core/messaging/persistmessage/message_service.go b/internal/pkg/core/messaging/persistmessage/message_persistence_service.go similarity index 84% rename from internal/pkg/core/messaging/persistmessage/message_service.go rename to internal/pkg/core/messaging/persistmessage/message_persistence_service.go index 163deb03..26c37226 100644 --- a/internal/pkg/core/messaging/persistmessage/message_service.go +++ b/internal/pkg/core/messaging/persistmessage/message_persistence_service.go @@ -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( @@ -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 } diff --git a/internal/pkg/core/serializer/json/json_serilizer_test.go b/internal/pkg/core/serializer/json/json_serilizer_test.go index 3877cb6e..d74342bb 100644 --- a/internal/pkg/core/serializer/json/json_serilizer_test.go +++ b/internal/pkg/core/serializer/json/json_serilizer_test.go @@ -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)) } @@ -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)) } @@ -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)) } diff --git a/internal/pkg/elasticsearch/elastic_options.go b/internal/pkg/elasticsearch/elastic_options.go index 56a89c3e..7fa66b86 100644 --- a/internal/pkg/elasticsearch/elastic_options.go +++ b/internal/pkg/elasticsearch/elastic_options.go @@ -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"` diff --git a/internal/pkg/eventstroredb/config/eventstoredb_options.go b/internal/pkg/eventstroredb/config/eventstoredb_options.go index 7f1d4bc7..3ee031a0 100644 --- a/internal/pkg/eventstroredb/config/eventstoredb_options.go +++ b/internal/pkg/eventstroredb/config/eventstoredb_options.go @@ -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) } diff --git a/internal/pkg/grpc/config/grpc_options.go b/internal/pkg/grpc/config/grpc_options.go index 0181e499..246ab3c8 100644 --- a/internal/pkg/grpc/config/grpc_options.go +++ b/internal/pkg/grpc/config/grpc_options.go @@ -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) { diff --git a/internal/pkg/http/customecho/config/echo_http_options.go b/internal/pkg/http/customecho/config/echo_http_options.go index c0c724b7..5c8e8558 100644 --- a/internal/pkg/http/customecho/config/echo_http_options.go +++ b/internal/pkg/http/customecho/config/echo_http_options.go @@ -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"` @@ -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 { diff --git a/internal/pkg/http/httperrors/customerrors/api_error.go b/internal/pkg/http/httperrors/customerrors/api_error.go index b451f925..6c6e72dd 100644 --- a/internal/pkg/http/httperrors/customerrors/api_error.go +++ b/internal/pkg/http/httperrors/customerrors/api_error.go @@ -4,22 +4,34 @@ import ( "emperror.dev/errors" ) -func NewApiError(message string, code int) error { - ae := &apiError{ - CustomError: NewCustomError(nil, code, message), +func NewApiError(message string, code int) ApiError { + // `NewPlain` doesn't add stack-trace at all + apiErrMessage := errors.NewPlain("api error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(apiErrMessage, message) + + apiError := &apiError{ + CustomError: NewCustomError(stackErr, code, message), } - stackErr := errors.WithStackIf(ae) - return stackErr + return apiError } -func NewApiErrorWrap(err error, code int, message string) error { - ae := &apiError{ - CustomError: NewCustomError(err, code, message), +func NewApiErrorWrap(err error, code int, message string) ApiError { + if err == nil { + return NewApiError(message, code) + } + + // `WithMessage` doesn't add stack-trace at all + apiErrMessage := errors.WithMessage(err, "api error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(apiErrMessage, message) + + apiError := &apiError{ + CustomError: NewCustomError(stackErr, code, message), } - stackErr := errors.WithStackIf(ae) - return stackErr + return apiError } type apiError struct { @@ -28,18 +40,24 @@ type apiError struct { type ApiError interface { CustomError + isAPIError() } -func (a *apiError) isAPIError() bool { - return true +func (a *apiError) isAPIError() { } func IsApiError(err error, code int) bool { - var apiError *apiError + var apiError ApiError + + // https://github.com/golang/go/blob/master/src/net/error_windows.go#L10C2-L12C3 + // this doesn't work for a nested api error, and we should use errors.As for traversing errors in all levels + if _, ok := err.(ApiError); ok { + return true + } - // us, ok := grpc_errors.Cause(err).(ApiError) + // us, ok := errors.Cause(err).(ApiError) if errors.As(err, &apiError) { - return apiError.isAPIError() && apiError.Status() == code + return apiError.Status() == code } return false diff --git a/internal/pkg/http/httperrors/customerrors/application_error.go b/internal/pkg/http/httperrors/customerrors/application_error.go index 91a6f5b2..dd716506 100644 --- a/internal/pkg/http/httperrors/customerrors/application_error.go +++ b/internal/pkg/http/httperrors/customerrors/application_error.go @@ -6,52 +6,46 @@ import ( "emperror.dev/errors" ) -func NewApplicationError(message string) error { - ae := &applicationError{ - CustomError: NewCustomError( - nil, - http.StatusInternalServerError, - message, - ), - } - stackErr := errors.WithStackIf(ae) - - return stackErr +func NewApplicationError(message string) ApplicationError { + return NewApplicationErrorWithCode(message, http.StatusInternalServerError) } -func NewApplicationErrorWithCode(message string, code int) error { - ae := &applicationError{ - CustomError: NewCustomError(nil, code, message), +func NewApplicationErrorWithCode(message string, code int) ApplicationError { + // `NewPlain` doesn't add stack-trace at all + applicationErrMessage := errors.NewPlain("application error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(applicationErrMessage, message) + + applicationError := &applicationError{ + CustomError: NewCustomError(stackErr, code, message), } - stackErr := errors.WithStackIf(ae) - return stackErr + return applicationError } -func NewApplicationErrorWrap(err error, message string) error { - ae := &applicationError{ - CustomError: NewCustomError( - err, - http.StatusInternalServerError, - message, - ), - } - stackErr := errors.WithStackIf(ae) - - return stackErr +func NewApplicationErrorWrap(err error, message string) ApplicationError { + return NewApplicationErrorWrapWithCode(err, http.StatusInternalServerError, message) } func NewApplicationErrorWrapWithCode( err error, code int, message string, -) error { - ae := &applicationError{ - CustomError: NewCustomError(err, code, message), +) ApplicationError { + if err == nil { + return NewApplicationErrorWithCode(message, code) } - stackErr := errors.WithStackIf(ae) - return stackErr + // `WithMessage` doesn't add stack-trace at all + applicationErrMessage := errors.WithMessage(err, "application error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(applicationErrMessage, message) + + applicationError := &applicationError{ + CustomError: NewCustomError(stackErr, code, message), + } + + return applicationError } type applicationError struct { @@ -60,18 +54,24 @@ type applicationError struct { type ApplicationError interface { CustomError + isApplicationError() } -func (a *applicationError) isApplicationError() bool { - return true +func (a *applicationError) isApplicationError() { } func IsApplicationError(err error, code int) bool { - var applicationError *applicationError - // us, ok := grpc_errors.Cause(err).(ApplicationError) + var applicationError ApplicationError + + // https://github.com/golang/go/blob/master/src/net/error_windows.go#L10C2-L12C3 + // this doesn't work for a nested application error, and we should use errors.As for traversing errors in all levels + if _, ok := err.(ApplicationError); ok { + return true + } + + // us, ok := errors.Cause(err).(ApplicationError) if errors.As(err, &applicationError) { - return applicationError.isApplicationError() && - applicationError.Status() == code + return applicationError.Status() == code } return false diff --git a/internal/pkg/http/httperrors/customerrors/bad_request_error.go b/internal/pkg/http/httperrors/customerrors/bad_request_error.go index c98a0640..84cf6662 100644 --- a/internal/pkg/http/httperrors/customerrors/bad_request_error.go +++ b/internal/pkg/http/httperrors/customerrors/bad_request_error.go @@ -6,22 +6,34 @@ import ( "emperror.dev/errors" ) -func NewBadRequestError(message string) error { - br := &badRequestError{ - CustomError: NewCustomError(nil, http.StatusBadRequest, message), +func NewBadRequestError(message string) BadRequestError { + // `NewPlain` doesn't add stack-trace at all + badRequestErrMessage := errors.NewPlain("bad request error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(badRequestErrMessage, message) + + badRequestError := &badRequestError{ + CustomError: NewCustomError(stackErr, http.StatusBadRequest, message), } - stackErr := errors.WithStackIf(br) - return stackErr + return badRequestError } -func NewBadRequestErrorWrap(err error, message string) error { - br := &badRequestError{ - CustomError: NewCustomError(err, http.StatusBadRequest, message), +func NewBadRequestErrorWrap(err error, message string) BadRequestError { + if err == nil { + return NewBadRequestError(message) + } + + // `WithMessage` doesn't add stack-trace at all + badRequestErrMessage := errors.WithMessage(err, "bad request error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(badRequestErrMessage, message) + + badRequestError := &badRequestError{ + CustomError: NewCustomError(stackErr, http.StatusBadRequest, message), } - stackErr := errors.WithStackIf(br) - return stackErr + return badRequestError } type badRequestError struct { @@ -30,17 +42,24 @@ type badRequestError struct { type BadRequestError interface { CustomError + isBadRequestError() } -func (b *badRequestError) isBadRequestError() bool { - return true +func (b *badRequestError) isBadRequestError() { } func IsBadRequestError(err error) bool { - var badRequestError *badRequestError - // us, ok := grpc_errors.Cause(err).(BadRequestError) + var badRequestError BadRequestError + + // https://github.com/golang/go/blob/master/src/net/error_windows.go#L10C2-L12C3 + // this doesn't work for a nested bad-request error, and we should use errors.As for traversing errors in all levels + if _, ok := err.(BadRequestError); ok { + return true + } + + // us, ok := errors.Cause(err).(BadRequestError) if errors.As(err, &badRequestError) { - return badRequestError.isBadRequestError() + return true } return false diff --git a/internal/pkg/http/httperrors/customerrors/conflict_error.go b/internal/pkg/http/httperrors/customerrors/conflict_error.go index 7361aa29..887236d0 100644 --- a/internal/pkg/http/httperrors/customerrors/conflict_error.go +++ b/internal/pkg/http/httperrors/customerrors/conflict_error.go @@ -6,22 +6,34 @@ import ( "emperror.dev/errors" ) -func NewConflictError(message string) error { - ce := &conflictError{ - CustomError: NewCustomError(nil, http.StatusConflict, message), +func NewConflictError(message string) ConflictError { + // `NewPlain` doesn't add stack-trace at all + conflictErrMessage := errors.NewPlain("conflict error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(conflictErrMessage, message) + + conflictError := &conflictError{ + CustomError: NewCustomError(stackErr, http.StatusConflict, message), } - stackErr := errors.WithStackIf(ce) - return stackErr + return conflictError } -func NewConflictErrorWrap(err error, message string) error { - ce := &conflictError{ - CustomError: NewCustomError(err, http.StatusConflict, message), +func NewConflictErrorWrap(err error, message string) ConflictError { + if err == nil { + return NewConflictError(message) + } + + // `WithMessage` doesn't add stack-trace at all + conflictErrMessage := errors.WithMessage(err, "conflict error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(conflictErrMessage, message) + + conflictError := &conflictError{ + CustomError: NewCustomError(stackErr, http.StatusConflict, message), } - stackErr := errors.WithStackIf(ce) - return stackErr + return conflictError } type conflictError struct { @@ -30,17 +42,24 @@ type conflictError struct { type ConflictError interface { CustomError + isConflictError() } -func (c *conflictError) isConflictError() bool { - return true +func (c *conflictError) isConflictError() { } func IsConflictError(err error) bool { - var conflictError *conflictError - // us, ok := grpc_errors.Cause(err).(ConflictError) + var conflictError ConflictError + + // https://github.com/golang/go/blob/master/src/net/error_windows.go#L10C2-L12C3 + // this doesn't work for a nested notfound error, and we should use errors.As for traversing errors in all levels + if _, ok := err.(ConflictError); ok { + return true + } + + // us, ok := errors.Cause(err).(ConflictError) if errors.As(err, &conflictError) { - return conflictError.isConflictError() + return true } return false diff --git a/internal/pkg/http/httperrors/customerrors/custom_errors.go b/internal/pkg/http/httperrors/customerrors/custom_errors.go index 58d51b46..361bd43d 100644 --- a/internal/pkg/http/httperrors/customerrors/custom_errors.go +++ b/internal/pkg/http/httperrors/customerrors/custom_errors.go @@ -20,7 +20,7 @@ import ( type customError struct { statusCode int message string - err error + error } type CustomError interface { @@ -28,7 +28,7 @@ type CustomError interface { contracts.Wrapper contracts.Causer contracts.Formatter - IsCustomError() bool + isCustomError() Status() int Message() string } @@ -36,20 +36,19 @@ type CustomError interface { func NewCustomError(err error, code int, message string) CustomError { m := &customError{ statusCode: code, - err: err, + error: err, message: message, } return m } -func (e *customError) IsCustomError() bool { - return true +func (e *customError) isCustomError() { } func (e *customError) Error() string { - if e.err != nil { - return e.message + ": " + e.err.Error() + if e.error != nil { + return e.error.Error() } return e.message @@ -64,19 +63,25 @@ func (e *customError) Status() int { } func (e *customError) Cause() error { - return e.err + return e.error } func (e *customError) Unwrap() error { - return e.err + return e.error } func (e *customError) Format(s fmt.State, verb rune) { switch verb { case 'v': if s.Flag('+') { - fmt.Fprintf(s, "%+v\n", e.Cause()) - io.WriteString(s, e.message) + //%s error messages separated by a colon and a space (": ") + //%q double-quoted error messages separated by a colon and a space (": ") + //%v one error message per line + //%+v one error message per line and stack trace (if any) + + // if we have a call-stacked error, +v shows callstack for this error + fmt.Fprintf(s, "%+v", e.Cause()) + // io.WriteString(s, e.message) return } fallthrough @@ -104,8 +109,9 @@ func IsCustomError(err error) bool { return true } + // us, ok := errors.Cause(err).(ConflictError) if errors.As(err, &customErr) { - return customErr.IsCustomError() + return true } return false diff --git a/internal/pkg/http/httperrors/customerrors/custom_errors_test.go b/internal/pkg/http/httperrors/customerrors/custom_errors_test.go index 60985897..53f40f77 100644 --- a/internal/pkg/http/httperrors/customerrors/custom_errors_test.go +++ b/internal/pkg/http/httperrors/customerrors/custom_errors_test.go @@ -2,6 +2,7 @@ package customErrors import ( "fmt" + "net/http" "testing" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/contracts" @@ -11,37 +12,48 @@ import ( "github.com/stretchr/testify/assert" ) -func Test_BadRequest_Err(t *testing.T) { - rootErr2 := NewBadRequestErrorWrap( +func Test_Domain_Err(t *testing.T) { + rootErr2 := NewDomainErrorWrap( nil, fmt.Sprintf("domain_events event already exists in event registry"), ) - rootErr := errors.New("handling bad request errorUtils") - badErr := NewBadRequestErrorWrap(rootErr, "this is a bad request errorUtils") - err := errors.WithMessage(badErr, "outer errorUtils wrapper") + // `NewPlain` doesn't add stack-trace but `New` will add stack-trace + rootErr := errors.NewPlain("handling domain_events errorUtils") + domainErr := NewDomainErrorWithCodeWrap(rootErr, 400, "this is a domain_events errorUtils") + err := errors.WithMessage(domainErr, "outer errorUtils wrapper") - assert.True(t, IsBadRequestError(err)) + assert.True(t, IsDomainError(err, 400)) + assert.True(t, IsDomainError(rootErr2, 400)) assert.True(t, IsCustomError(err)) assert.True(t, IsCustomError(rootErr2)) - assert.True(t, IsCustomError(rootErr2)) - var customError CustomError - var customError2 CustomError - errors.As(err, &customError) - errors.As(err, &customError2) + var domainError DomainError + errors.As(err, &domainError) - assert.NotNil(t, customError2) + _, isConflict := domainErr.(ConflictError) + _, isConflict2 := domainError.(ConflictError) + assert.False(t, isConflict) + assert.False(t, isConflict2) + + _, isDomainError := domainErr.(DomainError) + _, isDomainError2 := domainError.(DomainError) + assert.True(t, isDomainError) + assert.True(t, isDomainError2) + + assert.True(t, IsDomainError(domainErr, 400)) + assert.True(t, IsDomainError(domainError, 400)) + assert.False(t, IsDomainError(NewConflictError("conflict error"), 400)) - assert.Equal(t, 400, customError.Status()) - assert.Equal(t, "this is a bad request errorUtils", customError.Message()) + assert.Equal(t, 400, domainError.Status()) + assert.Equal(t, "this is a domain_events errorUtils", domainError.Message()) assert.Equal( t, - "this is a bad request errorUtils: handling bad request errorUtils", - customError.Error(), + "this is a domain_events errorUtils: domain error: handling domain_events errorUtils", + domainError.Error(), ) - assert.NotNil(t, customError.Unwrap()) - assert.NotNil(t, customError.Cause()) + assert.NotNil(t, domainError.Unwrap()) + assert.NotNil(t, domainError.Cause()) var stackErr contracts.StackTracer if ok := errors.As(err, &stackErr); ok { @@ -55,125 +67,236 @@ func Test_BadRequest_Err(t *testing.T) { } } -func Test_NotFound_Err(t *testing.T) { - rootErr := errors.New("handling not found errorUtils") - notFoundErr := NewNotFoundErrorWrap(rootErr, "this is a not found errorUtils") - err := errors.WithMessage(notFoundErr, "outer errorUtils wrapper") +func Test_Application_Err(t *testing.T) { + rootErr2 := NewApplicationErrorWrap( + nil, + fmt.Sprintf("domain_events event already exists in event registry"), + ) - assert.True(t, IsNotFoundError(err)) + // `NewPlain` doesn't add stack-trace but `New` will add stack-trace + rootErr := errors.NewPlain("handling application_exceptions errorUtils") + appErr := NewApplicationErrorWrapWithCode( + rootErr, + 400, + "this is a application_exceptions errorUtils", + ) + err := errors.WithMessage(appErr, "outer errorUtils wrapper") + + assert.True(t, IsApplicationError(err, 400)) + assert.True(t, IsApplicationError(rootErr2, 500)) assert.True(t, IsCustomError(err)) + assert.True(t, IsCustomError(rootErr2)) - var notFound NotFoundError - errors.As(err, ¬Found) + var applicationError ApplicationError + errors.As(err, &applicationError) - assert.Equal(t, 404, notFound.Status()) - assert.Equal(t, "this is a not found errorUtils", notFound.Message()) + _, isConflict := appErr.(ConflictError) + _, isConflict2 := applicationError.(ConflictError) + assert.False(t, isConflict) + assert.False(t, isConflict2) + + _, isApplicationError := appErr.(ApplicationError) + _, isApplicationError2 := applicationError.(ApplicationError) + assert.True(t, isApplicationError) + assert.True(t, isApplicationError2) + + assert.True(t, IsApplicationError(appErr, 400)) + assert.True(t, IsApplicationError(applicationError, 400)) + assert.False(t, IsApplicationError(NewConflictError("conflict error"), 400)) + + assert.Equal(t, 400, applicationError.Status()) + assert.Equal(t, "this is a application_exceptions errorUtils", applicationError.Message()) assert.Equal( t, - "this is a not found errorUtils: handling not found errorUtils", - notFound.Error(), + "this is a application_exceptions errorUtils: application error: handling application_exceptions errorUtils", + applicationError.Error(), ) - assert.NotNil(t, notFound.Unwrap()) - assert.NotNil(t, notFound.Cause()) + assert.NotNil(t, applicationError.Unwrap()) + assert.NotNil(t, applicationError.Cause()) var stackErr contracts.StackTracer if ok := errors.As(err, &stackErr); ok { // https://dave.cheney.net/2016/06/12/stack-traces-and-the-errors-package fmt.Println(errorUtils.ErrorsWithoutStack(err, false)) // Just write errorUtils messages for - fmt.Println( - errorUtils.ErrorsWithStack(err), - ) // write errorUtils messages with stacktrace + fmt.Println(errorUtils.ErrorsWithStack(err)) } else { fmt.Println(errorUtils.ErrorsWithoutStack(err, false)) } } -func Test_Domain_Err(t *testing.T) { - rootErr2 := NewDomainErrorWrap( +func Test_Api_Err(t *testing.T) { + rootErr2 := NewApiErrorWrap( nil, + http.StatusBadRequest, fmt.Sprintf("domain_events event already exists in event registry"), ) - rootErr := errors.New("handling domain_events errorUtils") - domainErr := NewDomainErrorWithCodeWrap(rootErr, 400, "this is a domain_events errorUtils") - err := errors.WithMessage(domainErr, "outer errorUtils wrapper") + // `NewPlain` doesn't add stack-trace but `New` will add stack-trace + rootErr := errors.NewPlain("handling api_exceptions errorUtils") + appErr := NewApiErrorWrap( + rootErr, + 400, + "this is a api_exceptions errorUtils", + ) + err := errors.WithMessage(appErr, "outer errorUtils wrapper") - assert.True(t, IsDomainError(err, 400)) - assert.True(t, IsDomainError(rootErr2, 400)) + assert.True(t, IsApiError(err, 400)) + assert.True(t, IsApiError(rootErr2, 500)) assert.True(t, IsCustomError(err)) assert.True(t, IsCustomError(rootErr2)) - var customError CustomError - errors.As(err, &customError) + var apiError ApiError + errors.As(err, &apiError) + + _, isConflict := appErr.(ConflictError) + _, isConflict2 := apiError.(ConflictError) + assert.False(t, isConflict) + assert.False(t, isConflict2) + + _, isApiError := appErr.(ApiError) + _, isApiError2 := apiError.(ApiError) + assert.True(t, isApiError) + assert.True(t, isApiError2) + + assert.True(t, IsApiError(appErr, 400)) + assert.True(t, IsApiError(apiError, 400)) + assert.False(t, IsApiError(NewConflictError("conflict error"), 400)) - assert.Equal(t, 400, customError.Status()) - assert.Equal(t, "this is a domain_events errorUtils", customError.Message()) + assert.Equal(t, 400, apiError.Status()) + assert.Equal(t, "this is a api_exceptions errorUtils", apiError.Message()) assert.Equal( t, - "this is a domain_events errorUtils: handling domain_events errorUtils", - customError.Error(), + "this is a api_exceptions errorUtils: api error: handling api_exceptions errorUtils", + apiError.Error(), ) - assert.NotNil(t, customError.Unwrap()) - assert.NotNil(t, customError.Cause()) + assert.NotNil(t, apiError.Unwrap()) + assert.NotNil(t, apiError.Cause()) var stackErr contracts.StackTracer if ok := errors.As(err, &stackErr); ok { // https://dave.cheney.net/2016/06/12/stack-traces-and-the-errors-package fmt.Println(errorUtils.ErrorsWithoutStack(err, false)) // Just write errorUtils messages for - fmt.Println( - errorUtils.ErrorsWithStack(err), - ) // write errorUtils messages with stacktrace + fmt.Println(errorUtils.ErrorsWithStack(err)) } else { fmt.Println(errorUtils.ErrorsWithoutStack(err, false)) } } -func Test_Application_Err(t *testing.T) { - rootErr2 := NewApplicationErrorWrap( +func Test_BadRequest_Err(t *testing.T) { + rootErr2 := NewBadRequestErrorWrap( nil, fmt.Sprintf("domain_events event already exists in event registry"), ) - rootErr := errors.New("handling application_exceptions errorUtils") - err := NewApplicationErrorWrapWithCode( - rootErr, - 400, - "this is a application_exceptions errorUtils", - ) - err = errors.WithMessage(err, "outer errorUtils wrapper") + // `NewPlain` doesn't add stack-trace but `New` will add stack-trace + rootErr := errors.NewPlain("handling bad request errorUtils") + badErr := NewBadRequestErrorWrap(rootErr, "this is a bad request errorUtils") + err := errors.WithMessage(badErr, "outer errorUtils wrapper") - assert.True(t, IsApplicationError(err, 400)) - assert.True(t, IsApplicationError(rootErr2, 500)) + assert.True(t, IsBadRequestError(err)) assert.True(t, IsCustomError(err)) assert.True(t, IsCustomError(rootErr2)) + assert.True(t, IsCustomError(rootErr2)) - var appErr ApplicationError - errors.As(err, &appErr) + var customError CustomError + var customError2 CustomError + errors.As(err, &customError) + errors.As(err, &customError2) + + assert.NotNil(t, customError2) + + var badRequestError BadRequestError + errors.As(err, &badRequestError) + + _, isConflict := badErr.(ConflictError) + _, isConflict2 := badRequestError.(ConflictError) + assert.False(t, isConflict) + assert.False(t, isConflict2) + + _, isBadRequest := badErr.(BadRequestError) + _, isBadRequest2 := badRequestError.(BadRequestError) + assert.True(t, isBadRequest) + assert.True(t, isBadRequest2) - assert.Equal(t, 400, appErr.Status()) - assert.Equal(t, "this is a application_exceptions errorUtils", appErr.Message()) + assert.True(t, IsBadRequestError(badErr)) + assert.True(t, IsBadRequestError(badRequestError)) + assert.False(t, IsBadRequestError(NewConflictError("conflict error"))) + + assert.Equal(t, 400, badRequestError.Status()) + assert.Equal(t, "this is a bad request errorUtils", badRequestError.Message()) assert.Equal( t, - "this is a application_exceptions errorUtils: handling application_exceptions errorUtils", - appErr.Error(), + "this is a bad request errorUtils: bad request error: handling bad request errorUtils", + badRequestError.Error(), ) - assert.NotNil(t, appErr.Unwrap()) - assert.NotNil(t, appErr.Cause()) + assert.NotNil(t, badRequestError.Unwrap()) + assert.NotNil(t, badRequestError.Cause()) var stackErr contracts.StackTracer if ok := errors.As(err, &stackErr); ok { // https://dave.cheney.net/2016/06/12/stack-traces-and-the-errors-package fmt.Println(errorUtils.ErrorsWithoutStack(err, false)) // Just write errorUtils messages for - fmt.Println(errorUtils.ErrorsWithStack(err)) + fmt.Println( + errorUtils.ErrorsWithStack(err), + ) // write errorUtils messages with stacktrace + } else { + fmt.Println(errorUtils.ErrorsWithoutStack(err, false)) + } +} + +func Test_NotFound_Err(t *testing.T) { + // `NewPlain` doesn't add stack-trace but `New` will add stack-trace + rootErr := errors.NewPlain("handling not found errorUtils") + notFoundErr := NewNotFoundErrorWrap(rootErr, "this is a not found errorUtils") + err := errors.WithMessage(notFoundErr, "outer errorUtils wrapper") + + assert.True(t, IsNotFoundError(err)) + assert.True(t, IsCustomError(err)) + + var notFound NotFoundError + errors.As(err, ¬Found) + + _, isConflict := notFoundErr.(ConflictError) + _, isConflict2 := notFound.(ConflictError) + assert.False(t, isConflict) + assert.False(t, isConflict2) + + _, isNotFound := notFoundErr.(NotFoundError) + _, isNotFound2 := notFound.(NotFoundError) + assert.True(t, isNotFound) + assert.True(t, isNotFound2) + + assert.True(t, IsNotFoundError(notFoundErr)) + assert.True(t, IsNotFoundError(notFound)) + assert.False(t, IsNotFoundError(NewConflictError("conflict error"))) + + assert.Equal(t, http.StatusNotFound, notFound.Status()) + assert.Equal(t, "this is a not found errorUtils", notFound.Message()) + assert.Equal( + t, + "this is a not found errorUtils: not found error: handling not found errorUtils", + notFound.Error(), + ) + assert.NotNil(t, notFound.Unwrap()) + assert.NotNil(t, notFound.Cause()) + + var stackErr contracts.StackTracer + if ok := errors.As(err, &stackErr); ok { + // https://dave.cheney.net/2016/06/12/stack-traces-and-the-errors-package + fmt.Println(errorUtils.ErrorsWithoutStack(err, false)) // Just write errorUtils messages for + fmt.Println( + errorUtils.ErrorsWithStack(err), + ) // write errorUtils messages with stacktrace } else { fmt.Println(errorUtils.ErrorsWithoutStack(err, false)) } } func Test_Internal_Server_Error(t *testing.T) { - rootErr := errors.New("handling internal server errorUtils") + // `NewPlain` doesn't add stack-trace but `New` will add stack-trace + rootErr := errors.NewPlain("handling internal server errorUtils") internalServerErr := NewInternalServerErrorWrap(rootErr, "this is a internal server errorUtils") - err := errors.WithMessage(internalServerErr, "this is a internal server errorUtils") + err := errors.WithMessage(internalServerErr, "outer errorUtils wrapper") assert.True(t, IsInternalServerError(err)) assert.True(t, IsCustomError(err)) @@ -181,11 +304,14 @@ func Test_Internal_Server_Error(t *testing.T) { var internalErr InternalServerError errors.As(err, &internalErr) - assert.Equal(t, 500, internalErr.Status()) + assert.True(t, IsInternalServerError(internalErr)) + assert.False(t, IsInternalServerError(NewConflictError("conflict error"))) + + assert.Equal(t, http.StatusInternalServerError, internalErr.Status()) assert.Equal(t, "this is a internal server errorUtils", internalErr.Message()) assert.Equal( t, - "this is a internal server errorUtils: handling internal server errorUtils", + "this is a internal server errorUtils: internal server error: handling internal server errorUtils", internalErr.Error(), ) assert.NotNil(t, internalErr.Unwrap()) @@ -201,15 +327,50 @@ func Test_Internal_Server_Error(t *testing.T) { } } +func Test_Forbidden_Error(t *testing.T) { + // `NewPlain` doesn't add stack-trace but `New` will add stack-trace + rootErr := errors.NewPlain("handling forbidden errorUtils") + forbiddenError := NewForbiddenErrorWrap(rootErr, "this is a forbidden errorUtils") + err := errors.WithMessage(forbiddenError, "outer errorUtils wrapper") + + assert.True(t, IsForbiddenError(err)) + assert.True(t, IsCustomError(err)) + + var forbiddenErr ForbiddenError + errors.As(err, &forbiddenErr) + + assert.True(t, IsForbiddenError(forbiddenErr)) + assert.False(t, IsForbiddenError(NewConflictError("conflict error"))) + + assert.Equal(t, http.StatusForbidden, forbiddenErr.Status()) + assert.Equal(t, "this is a forbidden errorUtils", forbiddenErr.Message()) + assert.Equal( + t, + "this is a forbidden errorUtils: forbidden error: handling forbidden errorUtils", + forbiddenErr.Error(), + ) + assert.NotNil(t, forbiddenErr.Unwrap()) + assert.NotNil(t, forbiddenErr.Cause()) + + var stackErr contracts.StackTracer + if ok := errors.As(err, &stackErr); ok { + // https://dave.cheney.net/2016/06/12/stack-traces-and-the-errors-package + fmt.Println(errorUtils.ErrorsWithoutStack(err, false)) // Just write errorUtils messages for + fmt.Println(errorUtils.ErrorsWithStack(err)) + } else { + fmt.Println(errorUtils.ErrorsWithStack(err)) + } +} + func Test_Marshaling_Error(t *testing.T) { rootErr2 := NewMarshalingErrorWrap( nil, fmt.Sprintf("domain_events event already exists in event registry"), ) - rootErr := errors.New("handling marshaling errorUtils") + rootErr := errors.NewPlain("handling marshaling errorUtils") marshalErr := NewMarshalingErrorWrap(rootErr, "this is a marshaling errorUtils") - err := errors.WithMessage(marshalErr, "this is a marshaling errorUtils") + err := errors.WithMessage(marshalErr, "outer errorUtils wrapper") assert.True(t, IsInternalServerError(err)) assert.True(t, IsInternalServerError(rootErr2)) @@ -219,24 +380,21 @@ func Test_Marshaling_Error(t *testing.T) { assert.True(t, IsMarshalingError(err)) assert.True(t, IsMarshalingError(rootErr2)) - var customErr CustomError - var customErr2 CustomError - - errors.As(err, &customErr) - errors.As(rootErr2, &customErr2) + var marshallingErr MarshalingError + errors.As(err, &marshallingErr) - assert.NotNil(t, customErr) - assert.NotNil(t, customErr2) + assert.True(t, IsMarshalingError(marshallingErr)) + assert.False(t, IsMarshalingError(NewConflictError("conflict error"))) - assert.Equal(t, 500, customErr.Status()) - assert.Equal(t, "this is a marshaling errorUtils", customErr.Message()) + assert.Equal(t, 500, marshallingErr.Status()) + assert.Equal(t, "this is a marshaling errorUtils", marshallingErr.Message()) assert.Equal( t, - "this is a marshaling errorUtils: handling marshaling errorUtils", - customErr.Error(), + "this is a marshaling errorUtils: marshaling error: handling marshaling errorUtils", + marshallingErr.Error(), ) - assert.NotNil(t, customErr.Unwrap()) - assert.NotNil(t, customErr.Cause()) + assert.NotNil(t, marshallingErr.Unwrap()) + assert.NotNil(t, marshallingErr.Cause()) var stackErr contracts.StackTracer if ok := errors.As(err, &stackErr); ok { @@ -256,7 +414,7 @@ func Test_Validation_Error(t *testing.T) { rootErr := errors.New("handling validation errorUtils") validationErr := NewValidationErrorWrap(rootErr, "this is a validation errorUtils") - err := errors.WithMessage(validationErr, "this is a validation errorUtils") + err := errors.WithMessage(validationErr, "this is a top error message") assert.True(t, IsBadRequestError(err)) assert.True(t, IsBadRequestError(rootErr2)) @@ -275,11 +433,11 @@ func Test_Validation_Error(t *testing.T) { assert.NotNil(t, customErr) assert.NotNil(t, customErr2) - assert.Equal(t, 400, customErr.Status()) + assert.Equal(t, http.StatusBadRequest, customErr.Status()) assert.Equal(t, "this is a validation errorUtils", customErr.Message()) assert.Equal( t, - "this is a validation errorUtils: handling validation errorUtils", + "this is a validation errorUtils: validation error: handling validation errorUtils", customErr.Error(), ) assert.NotNil(t, customErr.Unwrap()) @@ -301,31 +459,28 @@ func Test_Conflict_Error(t *testing.T) { fmt.Sprintf("domain_events event already exists in event registry"), ) - rootErr := errors.New("handling conflict errorUtils") + // `NewPlain` doesn't add stack-trace but `New` will add stack-trace + rootErr := errors.NewPlain("handling conflict errorUtils") conflictErr := NewConflictErrorWrap(rootErr, "this is a conflict errorUtils") - err := errors.WithMessage(conflictErr, "this is a conflict errorUtils") + err := errors.WithMessage(conflictErr, "this is a top error message") assert.True(t, IsCustomError(err)) assert.True(t, IsConflictError(err)) assert.True(t, IsCustomError(rootErr2)) assert.True(t, IsConflictError(rootErr2)) - var customErr CustomError - var customErr2 CustomError - errors.As(err, &customErr) - errors.As(rootErr2, &customErr2) - - assert.NotNil(t, customErr2) + var conflictError ConflictError + errors.As(err, &conflictError) - assert.Equal(t, 409, customErr.Status()) - assert.Equal(t, "this is a conflict errorUtils", customErr.Message()) + assert.Equal(t, 409, conflictError.Status()) + assert.Equal(t, "this is a conflict errorUtils", conflictError.Message()) assert.Equal( t, - "this is a conflict errorUtils: handling conflict errorUtils", - customErr.Error(), + "this is a conflict errorUtils: conflict error: handling conflict errorUtils", + conflictError.Error(), ) - assert.NotNil(t, customErr.Unwrap()) - assert.NotNil(t, customErr.Cause()) + assert.NotNil(t, conflictError.Unwrap()) + assert.NotNil(t, conflictError.Cause()) var stackErr contracts.StackTracer if ok := errors.As(err, &stackErr); ok { diff --git a/internal/pkg/http/httperrors/customerrors/domain_error.go b/internal/pkg/http/httperrors/customerrors/domain_error.go index 6a46dd4d..f10a779e 100644 --- a/internal/pkg/http/httperrors/customerrors/domain_error.go +++ b/internal/pkg/http/httperrors/customerrors/domain_error.go @@ -6,40 +6,42 @@ import ( "emperror.dev/errors" ) -func NewDomainError(message string) error { - de := &domainError{ - CustomError: NewCustomError(nil, http.StatusBadRequest, message), - } - stackErr := errors.WithStackIf(de) - - return stackErr +func NewDomainError(message string) DomainError { + return NewDomainErrorWithCode(message, http.StatusBadRequest) } -func NewDomainErrorWithCode(message string, code int) error { - de := &domainError{ - CustomError: NewCustomError(nil, code, message), +func NewDomainErrorWithCode(message string, code int) DomainError { + // `NewPlain` doesn't add stack-trace at all + domainErrMessage := errors.NewPlain("domain error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(domainErrMessage, message) + + domainError := &domainError{ + CustomError: NewCustomError(stackErr, code, message), } - stackErr := errors.WithStackIf(de) - return stackErr + return domainError +} + +func NewDomainErrorWrap(err error, message string) DomainError { + return NewDomainErrorWithCodeWrap(err, http.StatusBadRequest, message) } -func NewDomainErrorWrap(err error, message string) error { - de := &domainError{ - CustomError: NewCustomError(err, http.StatusBadRequest, message), +func NewDomainErrorWithCodeWrap(err error, code int, message string) DomainError { + if err == nil { + return NewDomainErrorWithCode(message, code) } - stackErr := errors.WithStackIf(de) - return stackErr -} + // `WithMessage` doesn't add stack-trace at all + domainErrMessage := errors.WithMessage(err, "domain error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(domainErrMessage, message) -func NewDomainErrorWithCodeWrap(err error, code int, message string) error { - de := &domainError{ - CustomError: NewCustomError(err, code, message), + domainError := &domainError{ + CustomError: NewCustomError(stackErr, code, message), } - stackErr := errors.WithStackIf(de) - return stackErr + return domainError } type domainError struct { @@ -48,17 +50,24 @@ type domainError struct { type DomainError interface { CustomError + isDomainError() } -func (d *domainError) isDomainError() bool { - return true +func (d *domainError) isDomainError() { } func IsDomainError(err error, code int) bool { - var domainErr *domainError - // us, ok := grpc_errors.Cause(err).(DomainError) + var domainErr DomainError + + // https://github.com/golang/go/blob/master/src/net/error_windows.go#L10C2-L12C3 + // this doesn't work for a nested notfound error, and we should use errors.As for traversing errors in all levels + if _, ok := err.(DomainError); ok { + return true + } + + // us, ok := errors.Cause(err).(DomainError) if errors.As(err, &domainErr) { - return domainErr.isDomainError() && domainErr.Status() == code + return domainErr.Status() == code } return false diff --git a/internal/pkg/http/httperrors/customerrors/forbiden_error.go b/internal/pkg/http/httperrors/customerrors/forbiden_error.go index ac285abf..0f91b1e4 100644 --- a/internal/pkg/http/httperrors/customerrors/forbiden_error.go +++ b/internal/pkg/http/httperrors/customerrors/forbiden_error.go @@ -6,22 +6,34 @@ import ( "emperror.dev/errors" ) -func NewForbiddenError(message string) error { - ne := &forbiddenError{ - CustomError: NewCustomError(nil, http.StatusForbidden, message), +func NewForbiddenError(message string) ForbiddenError { + // `NewPlain` doesn't add stack-trace at all + forbiddenErrMessage := errors.NewPlain("forbidden error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(forbiddenErrMessage, message) + + forbiddenError := &forbiddenError{ + CustomError: NewCustomError(stackErr, http.StatusForbidden, message), } - stackErr := errors.WithStackIf(ne) - return stackErr + return forbiddenError } -func NewForbiddenErrorWrap(err error, message string) error { - ne := &forbiddenError{ - CustomError: NewCustomError(err, http.StatusForbidden, message), +func NewForbiddenErrorWrap(err error, message string) ForbiddenError { + if err == nil { + return NewForbiddenError(message) + } + + // `WithMessage` doesn't add stack-trace at all + forbiddenErrMessage := errors.WithMessage(err, "forbidden error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(forbiddenErrMessage, message) + + forbiddenError := &forbiddenError{ + CustomError: NewCustomError(stackErr, http.StatusForbidden, message), } - stackErr := errors.WithStackIf(ne) - return stackErr + return forbiddenError } type forbiddenError struct { @@ -30,17 +42,24 @@ type forbiddenError struct { type ForbiddenError interface { CustomError + isForbiddenError() } -func (f *forbiddenError) isForbiddenError() bool { - return true +func (f *forbiddenError) isForbiddenError() { } func IsForbiddenError(err error) bool { - var forbiddenError *forbiddenError - // us, ok := grpc_errors.Cause(err).(ForbiddenError) + var forbiddenError ForbiddenError + + // https://github.com/golang/go/blob/master/src/net/error_windows.go#L10C2-L12C3 + // this doesn't work for a nested forbidden error, and we should use errors.As for traversing errors in all levels + if _, ok := err.(ForbiddenError); ok { + return true + } + + // us, ok := errors.Cause(err).(ForbiddenError) if errors.As(err, &forbiddenError) { - return forbiddenError.isForbiddenError() + return true } return false diff --git a/internal/pkg/http/httperrors/customerrors/internal_server_error.go b/internal/pkg/http/httperrors/customerrors/internal_server_error.go index 391d6156..b2818574 100644 --- a/internal/pkg/http/httperrors/customerrors/internal_server_error.go +++ b/internal/pkg/http/httperrors/customerrors/internal_server_error.go @@ -6,22 +6,34 @@ import ( "emperror.dev/errors" ) -func NewInternalServerError(message string) error { - br := &internalServerError{ - CustomError: NewCustomError(nil, http.StatusInternalServerError, message), +func NewInternalServerError(message string) InternalServerError { + // `NewPlain` doesn't add stack-trace at all + internalErrMessage := errors.NewPlain("internal server error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(internalErrMessage, message) + + internalServerError := &internalServerError{ + CustomError: NewCustomError(stackErr, http.StatusInternalServerError, message), } - stackErr := errors.WithStackIf(br) - return stackErr + return internalServerError } -func NewInternalServerErrorWrap(err error, message string) error { - br := &internalServerError{ - CustomError: NewCustomError(err, http.StatusInternalServerError, message), +func NewInternalServerErrorWrap(err error, message string) InternalServerError { + if err == nil { + return NewInternalServerError(message) + } + + // `WithMessage` doesn't add stack-trace at all + internalErrMessage := errors.WithMessage(err, "internal server error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(internalErrMessage, message) + + internalServerError := &internalServerError{ + CustomError: NewCustomError(stackErr, http.StatusInternalServerError, message), } - stackErr := errors.WithStackIf(br) - return stackErr + return internalServerError } type internalServerError struct { @@ -30,17 +42,24 @@ type internalServerError struct { type InternalServerError interface { CustomError + isInternalServerError() } -func (i *internalServerError) isInternalServerError() bool { - return true +func (i *internalServerError) isInternalServerError() { } func IsInternalServerError(err error) bool { - var internalErr *internalServerError - // us, ok := grpc_errors.Cause(err).(InternalServerError) - if errors.As(err, &internalErr) { - return internalErr.isInternalServerError() + var internalServerErr InternalServerError + + // https://github.com/golang/go/blob/master/src/net/error_windows.go#L10C2-L12C3 + // this doesn't work for a nested internal server error, and we should use errors.As for traversing errors in all levels + if _, ok := err.(InternalServerError); ok { + return true + } + + // us, ok := errors.Cause(err).(InternalServerError) + if errors.As(err, &internalServerErr) { + return true } return false diff --git a/internal/pkg/http/httperrors/customerrors/marshaling_error.go b/internal/pkg/http/httperrors/customerrors/marshaling_error.go index 0520588a..04c09637 100644 --- a/internal/pkg/http/httperrors/customerrors/marshaling_error.go +++ b/internal/pkg/http/httperrors/customerrors/marshaling_error.go @@ -1,49 +1,68 @@ package customErrors import ( + "net/http" + "emperror.dev/errors" ) -func NewMarshalingError(message string) error { - internal := NewInternalServerError(message) - customErr := GetCustomError(internal) - ue := &marshalingError{ - InternalServerError: customErr.(InternalServerError), +func NewMarshalingError(message string) MarshalingError { + // `NewPlain` doesn't add stack-trace at all + marshalingErrMessage := errors.NewPlain("marshaling error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(marshalingErrMessage, message) + + marshalingError := &marshalingError{ + CustomError: NewCustomError(stackErr, http.StatusInternalServerError, message), } - stackErr := errors.WithStackIf(ue) - return stackErr + return marshalingError } -func NewMarshalingErrorWrap(err error, message string) error { - internal := NewInternalServerErrorWrap(err, message) - customErr := GetCustomError(internal) - ue := &marshalingError{ - InternalServerError: customErr.(InternalServerError), +func NewMarshalingErrorWrap(err error, message string) MarshalingError { + if err == nil { + return NewMarshalingError(message) + } + + // `WithMessage` doesn't add stack-trace at all + marshalingErrMessage := errors.WithMessage(err, "marshaling error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(marshalingErrMessage, message) + + marshalingError := &marshalingError{ + CustomError: NewCustomError(stackErr, http.StatusInternalServerError, message), } - stackErr := errors.WithStackIf(ue) - return stackErr + return marshalingError } type marshalingError struct { - InternalServerError + CustomError } type MarshalingError interface { InternalServerError + isMarshalingError() +} + +func (m *marshalingError) isMarshalingError() { } -func (m *marshalingError) isMarshalingError() bool { - return true +func (m *marshalingError) isInternalServerError() { } func IsMarshalingError(err error) bool { - var me *marshalingError + var marshalingErr MarshalingError + + // https://github.com/golang/go/blob/master/src/net/error_windows.go#L10C2-L12C3 + // this doesn't work for a nested marshaling error, and we should use errors.As for traversing errors in all levels + if _, ok := err.(MarshalingError); ok { + return true + } - // us, ok := grpc_errors.Cause(err).(MarshalingError) - if errors.As(err, &me) { - return me.isMarshalingError() + // us, ok := errors.Cause(err).(MarshalingError) + if errors.As(err, &marshalingErr) { + return true } return false diff --git a/internal/pkg/http/httperrors/customerrors/not_found_error.go b/internal/pkg/http/httperrors/customerrors/not_found_error.go index 24f2c7c0..ed70336d 100644 --- a/internal/pkg/http/httperrors/customerrors/not_found_error.go +++ b/internal/pkg/http/httperrors/customerrors/not_found_error.go @@ -6,22 +6,34 @@ import ( "emperror.dev/errors" ) -func NewNotFoundError(message string) error { - ne := ¬FoundError{ - CustomError: NewCustomError(nil, http.StatusNotFound, message), +func NewNotFoundError(message string) NotFoundError { + // `NewPlain` doesn't add stack-trace at all + notFoundErrMessage := errors.NewPlain("not found error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(notFoundErrMessage, message) + + notFoundError := ¬FoundError{ + CustomError: NewCustomError(stackErr, http.StatusBadRequest, message), } - stackErr := errors.WithStackIf(ne) - return stackErr + return notFoundError } -func NewNotFoundErrorWrap(err error, message string) error { - ne := ¬FoundError{ - CustomError: NewCustomError(err, http.StatusNotFound, message), +func NewNotFoundErrorWrap(err error, message string) NotFoundError { + if err == nil { + return NewNotFoundError(message) + } + + // `WithMessage` doesn't add stack-trace at all + notFoundErrMessage := errors.WithMessage(err, "not found error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(notFoundErrMessage, message) + + notFoundError := ¬FoundError{ + CustomError: NewCustomError(stackErr, http.StatusNotFound, message), } - stackErr := errors.WithStackIf(ne) - return stackErr + return notFoundError } type notFoundError struct { @@ -30,17 +42,24 @@ type notFoundError struct { type NotFoundError interface { CustomError + isNotFoundError() } -func (n *notFoundError) isNotFoundError() bool { - return true +func (n *notFoundError) isNotFoundError() { } func IsNotFoundError(err error) bool { - var notFoundError *notFoundError - // us, ok := grpc_errors.Cause(err).(NotFoundError) + var notFoundError NotFoundError + + // https://github.com/golang/go/blob/master/src/net/error_windows.go#L10C2-L12C3 + // this doesn't work for a nested notfound error, and we should use errors.As for traversing errors in all levels + if _, ok := err.(NotFoundError); ok { + return true + } + + // us, ok := errors.Cause(err).(NotFoundError) if errors.As(err, ¬FoundError) { - return notFoundError.isNotFoundError() + return true } return false diff --git a/internal/pkg/http/httperrors/customerrors/unauthorized_error.go b/internal/pkg/http/httperrors/customerrors/unauthorized_error.go index d7e66d16..2a6cc25e 100644 --- a/internal/pkg/http/httperrors/customerrors/unauthorized_error.go +++ b/internal/pkg/http/httperrors/customerrors/unauthorized_error.go @@ -6,22 +6,34 @@ import ( "emperror.dev/errors" ) -func NewUnAuthorizedError(message string) error { - ue := &unauthorizedError{ - CustomError: NewCustomError(nil, http.StatusUnauthorized, message), +func NewUnAuthorizedError(message string) UnauthorizedError { + // `NewPlain` doesn't add stack-trace at all + unAuthorizedErrMessage := errors.NewPlain("unauthorized error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(unAuthorizedErrMessage, message) + + unAuthorizedError := &unauthorizedError{ + CustomError: NewCustomError(stackErr, http.StatusUnauthorized, message), } - stackErr := errors.WithStackIf(ue) - return stackErr + return unAuthorizedError } -func NewUnAuthorizedErrorWrap(err error, message string) error { - ue := &unauthorizedError{ - CustomError: NewCustomError(err, http.StatusUnauthorized, message), +func NewUnAuthorizedErrorWrap(err error, message string) UnauthorizedError { + if err == nil { + return NewUnAuthorizedError(message) + } + + // `WithMessage` doesn't add stack-trace at all + unAuthorizedErrMessage := errors.WithMessage(err, "unauthorized error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(unAuthorizedErrMessage, message) + + unAuthorizedError := &unauthorizedError{ + CustomError: NewCustomError(stackErr, http.StatusUnauthorized, message), } - stackErr := errors.WithStackIf(ue) - return stackErr + return unAuthorizedError } type unauthorizedError struct { @@ -30,17 +42,24 @@ type unauthorizedError struct { type UnauthorizedError interface { CustomError + isUnAuthorizedError() } -func (u *unauthorizedError) isUnAuthorizedError() bool { - return true +func (u *unauthorizedError) isUnAuthorizedError() { } func IsUnAuthorizedError(err error) bool { - var unauthorizedError *unauthorizedError - // us, ok := grpc_errors.Cause(err).(UnauthorizedError) + var unauthorizedError UnauthorizedError + + // https://github.com/golang/go/blob/master/src/net/error_windows.go#L10C2-L12C3 + // this doesn't work for a nested unauthorized error, and we should use errors.As for traversing errors in all levels + if _, ok := err.(UnauthorizedError); ok { + return true + } + + // us, ok := errors.Cause(err).(UnauthorizedError) if errors.As(err, &unauthorizedError) { - return unauthorizedError.isUnAuthorizedError() + return true } return false diff --git a/internal/pkg/http/httperrors/customerrors/unmarshaling_error.go b/internal/pkg/http/httperrors/customerrors/unmarshaling_error.go index 58c5b713..e6bbea35 100644 --- a/internal/pkg/http/httperrors/customerrors/unmarshaling_error.go +++ b/internal/pkg/http/httperrors/customerrors/unmarshaling_error.go @@ -1,48 +1,68 @@ package customErrors import ( + "net/http" + "emperror.dev/errors" ) -func NewUnMarshalingError(message string) error { - internal := NewInternalServerError(message) - customErr := GetCustomError(internal) - ue := &unMarshalingError{ - InternalServerError: customErr.(InternalServerError), +func NewUnMarshalingError(message string) UnMarshalingError { + // `NewPlain` doesn't add stack-trace at all + unMarshalingErrMessage := errors.NewPlain("unMarshaling error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(unMarshalingErrMessage, message) + + unMarshalingError := &unMarshalingError{ + CustomError: NewCustomError(stackErr, http.StatusInternalServerError, message), } - stackErr := errors.WithStackIf(ue) - return stackErr + return unMarshalingError } -func NewUnMarshalingErrorWrap(err error, message string) error { - internal := NewInternalServerErrorWrap(err, message) - customErr := GetCustomError(internal) - ue := &unMarshalingError{ - InternalServerError: customErr.(InternalServerError), +func NewUnMarshalingErrorWrap(err error, message string) UnMarshalingError { + if err == nil { + return NewUnMarshalingError(message) + } + + // `WithMessage` doesn't add stack-trace at all + unMarshalingErrMessage := errors.WithMessage(err, "unMarshaling error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(unMarshalingErrMessage, message) + + unMarshalingError := &unMarshalingError{ + CustomError: NewCustomError(stackErr, http.StatusInternalServerError, message), } - stackErr := errors.WithStackIf(ue) - return stackErr + return unMarshalingError } type unMarshalingError struct { - InternalServerError + CustomError } type UnMarshalingError interface { InternalServerError + isUnMarshalingError() } -func (u *unMarshalingError) isUnMarshalingError() bool { - return true +func (u *unMarshalingError) isUnMarshalingError() { +} + +func (u *unMarshalingError) isInternalServerError() { } func IsUnMarshalingError(err error) bool { - var unMarshalingError *unMarshalingError - // us, ok := grpc_errors.Cause(err).(UnMarshalingError) + var unMarshalingError UnMarshalingError + + // https://github.com/golang/go/blob/master/src/net/error_windows.go#L10C2-L12C3 + // this doesn't work for a nested unMarshaling error, and we should use errors.As for traversing errors in all levels + if _, ok := err.(UnMarshalingError); ok { + return true + } + + // us, ok := errors.Cause(err).(UnMarshalingError) if errors.As(err, &unMarshalingError) { - return unMarshalingError.isUnMarshalingError() + return true } return false diff --git a/internal/pkg/http/httperrors/customerrors/validation_error.go b/internal/pkg/http/httperrors/customerrors/validation_error.go index 938501fb..74164940 100644 --- a/internal/pkg/http/httperrors/customerrors/validation_error.go +++ b/internal/pkg/http/httperrors/customerrors/validation_error.go @@ -1,48 +1,68 @@ package customErrors import ( + "net/http" + "emperror.dev/errors" ) -func NewValidationError(message string) error { - bad := NewBadRequestError(message) - customErr := GetCustomError(bad) - ue := &validationError{ - BadRequestError: customErr.(BadRequestError), +func NewValidationError(message string) ValidationError { + // `NewPlain` doesn't add stack-trace at all + validationErrMessage := errors.NewPlain("validation error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(validationErrMessage, message) + + validationError := &validationError{ + CustomError: NewCustomError(stackErr, http.StatusBadRequest, message), } - stackErr := errors.WithStackIf(ue) - return stackErr + return validationError } -func NewValidationErrorWrap(err error, message string) error { - bad := NewBadRequestErrorWrap(err, message) - customErr := GetCustomError(bad) - ue := &validationError{ - BadRequestError: customErr.(BadRequestError), +func NewValidationErrorWrap(err error, message string) ValidationError { + if err == nil { + return NewValidationError(message) + } + + // `WithMessage` doesn't add stack-trace at all + validationErrMessage := errors.WithMessage(err, "validation error") + // `WrapIf` add stack-trace if not added before + stackErr := errors.WrapIf(validationErrMessage, message) + + validationError := &validationError{ + CustomError: NewCustomError(stackErr, http.StatusBadRequest, message), } - stackErr := errors.WithStackIf(ue) - return stackErr + return validationError } type validationError struct { - BadRequestError + CustomError } type ValidationError interface { BadRequestError + isValidationError() } -func (v *validationError) isValidationError() bool { - return true +func (v *validationError) isValidationError() { +} + +func (v *validationError) isBadRequestError() { } func IsValidationError(err error) bool { - var validationError *validationError - // us, ok := grpc_errors.Cause(err).(ValidationError) + var validationError ValidationError + + // https://github.com/golang/go/blob/master/src/net/error_windows.go#L10C2-L12C3 + // this doesn't work for a nested validation error, and we should use errors.As for traversing errors in all levels + if _, ok := err.(ValidationError); ok { + return true + } + + // us, ok := errors.Cause(err).(ValidationError) if errors.As(err, &validationError) { - return validationError.isValidationError() + return true } return false diff --git a/internal/pkg/http/httperrors/problemdetails/problem_details.go b/internal/pkg/http/httperrors/problemdetails/problem_details.go index f2c7f66b..4a6f76c0 100644 --- a/internal/pkg/http/httperrors/problemdetails/problem_details.go +++ b/internal/pkg/http/httperrors/problemdetails/problem_details.go @@ -160,7 +160,7 @@ func NewProblemDetailFromCodeAndDetail( } func Map[E error](problem ProblemDetailFunc[E]) { - errorType := typeMapper.GetTypeFromGeneric[E]() + errorType := typeMapper.GetGenericTypeByT[E]() if errorType.Kind() == reflect.Interface { types := typeMapper.TypesImplementedInterface[E]() for _, t := range types { diff --git a/internal/pkg/logger/config/log_options.go b/internal/pkg/logger/config/log_options.go index 69ab106a..827f0591 100644 --- a/internal/pkg/logger/config/log_options.go +++ b/internal/pkg/logger/config/log_options.go @@ -9,7 +9,7 @@ import ( "github.com/iancoleman/strcase" ) -var optionName = strcase.ToLowerCamel(typeMapper.GetTypeNameByT[LogOptions]()) +var optionName = strcase.ToLowerCamel(typeMapper.GetGenericTypeNameByT[LogOptions]()) type LogOptions struct { LogLevel string `mapstructure:"level"` diff --git a/internal/pkg/migration/migration_options.go b/internal/pkg/migration/migration_options.go index 9e442539..b6c8701d 100644 --- a/internal/pkg/migration/migration_options.go +++ b/internal/pkg/migration/migration_options.go @@ -28,7 +28,7 @@ type MigrationOptions struct { } func ProvideConfig(environment environment.Environment) (*MigrationOptions, error) { - optionName := strcase.ToLowerCamel(typeMapper.GetTypeNameByT[MigrationOptions]()) + optionName := strcase.ToLowerCamel(typeMapper.GetGenericTypeNameByT[MigrationOptions]()) return config.BindConfigKey[*MigrationOptions](optionName, environment) } diff --git a/internal/pkg/mongodb/mongo_options.go b/internal/pkg/mongodb/mongo_options.go index e75e3d62..75810244 100644 --- a/internal/pkg/mongodb/mongo_options.go +++ b/internal/pkg/mongodb/mongo_options.go @@ -22,7 +22,7 @@ func provideConfig( environment environment.Environment, ) (*MongoDbOptions, error) { optionName := strcase.ToLowerCamel( - typeMapper.GetTypeNameByT[MongoDbOptions](), + typeMapper.GetGenericTypeNameByT[MongoDbOptions](), ) return config.BindConfigKey[*MongoDbOptions](optionName, environment) } diff --git a/internal/pkg/mongodb/repository/mongo_generic_repository.go b/internal/pkg/mongodb/repository/mongo_generic_repository.go index 13f7464d..e1c284ba 100644 --- a/internal/pkg/mongodb/repository/mongo_generic_repository.go +++ b/internal/pkg/mongodb/repository/mongo_generic_repository.go @@ -65,8 +65,8 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) Add( ctx context.Context, entity TEntity, ) error { - dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() - modelType := typeMapper.GetTypeFromGeneric[TEntity]() + dataModelType := typeMapper.GetGenericTypeByT[TDataModel]() + modelType := typeMapper.GetGenericTypeByT[TEntity]() collection := m.db.Database(m.databaseName).Collection(m.collectionName) @@ -112,8 +112,8 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) GetById( ctx context.Context, id uuid.UUID, ) (TEntity, error) { - dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() - modelType := typeMapper.GetTypeFromGeneric[TEntity]() + dataModelType := typeMapper.GetGenericTypeByT[TDataModel]() + modelType := typeMapper.GetGenericTypeByT[TEntity]() collection := m.db.Database(m.databaseName).Collection(m.collectionName) if modelType == dataModelType { @@ -163,8 +163,8 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) GetAll( ctx context.Context, listQuery *utils.ListQuery, ) (*utils.ListResult[TEntity], error) { - dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() - modelType := typeMapper.GetTypeFromGeneric[TEntity]() + dataModelType := typeMapper.GetGenericTypeByT[TDataModel]() + modelType := typeMapper.GetGenericTypeByT[TEntity]() collection := m.db.Database(m.databaseName).Collection(m.collectionName) if modelType == dataModelType { @@ -196,13 +196,13 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) Search( searchTerm string, listQuery *utils.ListQuery, ) (*utils.ListResult[TEntity], error) { - dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() - modelType := typeMapper.GetTypeFromGeneric[TEntity]() + dataModelType := typeMapper.GetGenericTypeByT[TDataModel]() + modelType := typeMapper.GetGenericTypeByT[TEntity]() collection := m.db.Database(m.databaseName).Collection(m.collectionName) if modelType == dataModelType { fields := reflectionHelper.GetAllFields( - typeMapper.GetTypeFromGeneric[TEntity](), + typeMapper.GetGenericTypeByT[TEntity](), ) var a bson.A for _, field := range fields { @@ -231,7 +231,7 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) Search( } return result, nil } else { - fields := reflectionHelper.GetAllFields(typeMapper.GetTypeFromGeneric[TDataModel]()) + fields := reflectionHelper.GetAllFields(typeMapper.GetGenericTypeByT[TDataModel]()) var a bson.A for _, field := range fields { if field.Type.Kind() != reflect.String { @@ -259,8 +259,8 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) GetByFilter( ctx context.Context, filters map[string]interface{}, ) ([]TEntity, error) { - dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() - modelType := typeMapper.GetTypeFromGeneric[TEntity]() + dataModelType := typeMapper.GetGenericTypeByT[TDataModel]() + modelType := typeMapper.GetGenericTypeByT[TEntity]() collection := m.db.Database(m.databaseName).Collection(m.collectionName) // we could use also bson.D{} for filtering, it is also a map @@ -313,8 +313,8 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) FirstOrDefault( ctx context.Context, filters map[string]interface{}, ) (TEntity, error) { - dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() - modelType := typeMapper.GetTypeFromGeneric[TEntity]() + dataModelType := typeMapper.GetGenericTypeByT[TDataModel]() + modelType := typeMapper.GetGenericTypeByT[TEntity]() collection := m.db.Database(m.databaseName).Collection(m.collectionName) if modelType == dataModelType { @@ -351,8 +351,8 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) Update( ctx context.Context, entity TEntity, ) error { - dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() - modelType := typeMapper.GetTypeFromGeneric[TEntity]() + dataModelType := typeMapper.GetGenericTypeByT[TDataModel]() + modelType := typeMapper.GetGenericTypeByT[TEntity]() collection := m.db.Database(m.databaseName).Collection(m.collectionName) ops := options.FindOneAndUpdate() ops.SetReturnDocument(options.After) @@ -434,8 +434,8 @@ func (m *mongoGenericRepository[TDataModel, TEntity]) SkipTake( skip int, take int, ) ([]TEntity, error) { - dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() - modelType := typeMapper.GetTypeFromGeneric[TEntity]() + dataModelType := typeMapper.GetGenericTypeByT[TDataModel]() + modelType := typeMapper.GetGenericTypeByT[TEntity]() collection := m.db.Database(m.databaseName).Collection(m.collectionName) l := int64(take) s := int64(skip) diff --git a/internal/pkg/otel/metrics/messaging/pipeline/messaging_metrics_pipeline.go b/internal/pkg/otel/metrics/messaging/pipeline/messaging_metrics_pipeline.go index b11a461c..c70c6881 100644 --- a/internal/pkg/otel/metrics/messaging/pipeline/messaging_metrics_pipeline.go +++ b/internal/pkg/otel/metrics/messaging/pipeline/messaging_metrics_pipeline.go @@ -148,7 +148,7 @@ func (m *messagingMetricsPipeline) Handle( // // switch { // case strings.Contains(typeMapper.GetPackageName(request), "command") || strings.Contains(typeMapper.GetPackageName(request), "commands"): -// requestNameAttribute = app.CommandName +// requestNameAttribute = app.ShortTypeName // requestAttribute = app.Command // requestResultName = app.CommandResultName // requestResult = app.CommandResult diff --git a/internal/pkg/otel/metrics/metrics_options.go b/internal/pkg/otel/metrics/metrics_options.go index 62a50a78..5ead8960 100644 --- a/internal/pkg/otel/metrics/metrics_options.go +++ b/internal/pkg/otel/metrics/metrics_options.go @@ -35,7 +35,7 @@ func ProvideMetricsConfig( environment environment.Environment, ) (*MetricsOptions, error) { optionName := strcase.ToLowerCamel( - typeMapper.GetTypeNameByT[MetricsOptions](), + typeMapper.GetGenericTypeNameByT[MetricsOptions](), ) return config.BindConfigKey[*MetricsOptions](optionName, environment) diff --git a/internal/pkg/otel/tracing/tracing_options.go b/internal/pkg/otel/tracing/tracing_options.go index a72c26f0..4bd699b9 100644 --- a/internal/pkg/otel/tracing/tracing_options.go +++ b/internal/pkg/otel/tracing/tracing_options.go @@ -41,7 +41,7 @@ func ProvideTracingConfig( environment environment.Environment, ) (*TracingOptions, error) { optionName := strcase.ToLowerCamel( - typeMapper.GetTypeNameByT[TracingOptions](), + typeMapper.GetGenericTypeNameByT[TracingOptions](), ) return config.BindConfigKey[*TracingOptions](optionName, environment) diff --git a/internal/pkg/postgresgorm/contracts/gorm_dbcontext.go b/internal/pkg/postgresgorm/contracts/gorm_dbcontext.go index 9afeaf8b..6a78611b 100644 --- a/internal/pkg/postgresgorm/contracts/gorm_dbcontext.go +++ b/internal/pkg/postgresgorm/contracts/gorm_dbcontext.go @@ -6,11 +6,11 @@ import ( "gorm.io/gorm" ) -type IGormDBContext interface { - WithTx(ctx context.Context) (IGormDBContext, error) - WithTxIfExists(ctx context.Context) IGormDBContext +type GormDBContext interface { + WithTx(ctx context.Context) (GormDBContext, error) + WithTxIfExists(ctx context.Context) GormDBContext RunInTx(ctx context.Context, action ActionFunc) error DB() *gorm.DB } -type ActionFunc func(ctx context.Context, gormContext IGormDBContext) error +type ActionFunc func(ctx context.Context, gormContext GormDBContext) error diff --git a/internal/pkg/postgresgorm/gorm_options.go b/internal/pkg/postgresgorm/gorm_options.go index 00d8c8be..c0dbd574 100644 --- a/internal/pkg/postgresgorm/gorm_options.go +++ b/internal/pkg/postgresgorm/gorm_options.go @@ -11,7 +11,7 @@ import ( "github.com/iancoleman/strcase" ) -var optionName = strcase.ToLowerCamel(typeMapper.GetTypeNameByT[GormOptions]()) +var optionName = strcase.ToLowerCamel(typeMapper.GetGenericTypeNameByT[GormOptions]()) type GormOptions struct { UseInMemory bool `mapstructure:"useInMemory"` diff --git a/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext.go b/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext.go index a23de298..743c3ed5 100644 --- a/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext.go +++ b/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext.go @@ -14,7 +14,7 @@ type gormDBContext struct { db *gorm.DB } -func NewGormDBContext(db *gorm.DB) contracts.IGormDBContext { +func NewGormDBContext(db *gorm.DB) contracts.GormDBContext { c := &gormDBContext{db: db} return c @@ -27,7 +27,7 @@ func (c *gormDBContext) DB() *gorm.DB { // WithTx creates a transactional DBContext with getting tx-gorm from the ctx. This will throw an error if the transaction does not exist. func (c *gormDBContext) WithTx( ctx context.Context, -) (contracts.IGormDBContext, error) { +) (contracts.GormDBContext, error) { tx, err := gormextensions.GetTxFromContext(ctx) if err != nil { return nil, err @@ -39,7 +39,7 @@ func (c *gormDBContext) WithTx( // WithTxIfExists creates a transactional DBContext with getting tx-gorm from the ctx. not throw an error if the transaction is not existing and returns an existing database. func (c *gormDBContext) WithTxIfExists( ctx context.Context, -) contracts.IGormDBContext { +) contracts.GormDBContext { tx := gormextensions.GetTxFromContextIfExists(ctx) if tx == nil { return c diff --git a/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext_extensions.go b/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext_extensions.go index 16241a48..f43459f8 100644 --- a/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext_extensions.go +++ b/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext_extensions.go @@ -17,7 +17,7 @@ import ( func Exists[TDataModel interface{}]( ctx context.Context, - dbContext contracts.IGormDBContext, + dbContext contracts.GormDBContext, id uuid.UUID, ) bool { var count int64 @@ -31,7 +31,7 @@ func Exists[TDataModel interface{}]( func FindModelByID[TDataModel interface{}, TModel interface{}]( ctx context.Context, - dbContext contracts.IGormDBContext, + dbContext contracts.GormDBContext, id uuid.UUID, ) (TModel, error) { var dataModel TDataModel @@ -44,8 +44,8 @@ func FindModelByID[TDataModel interface{}, TModel interface{}]( // result := c.WithContext(ctx).First(&TDataModel{Id: id}) // result := c.WithContext(ctx).Scopes(scopes.FilterByID(id)).First(&dataModel) - modelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TModel]()) - dataModelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TDataModel]()) + modelName := strcase.ToSnake(typeMapper.GetGenericNonePointerTypeNameByT[TModel]()) + dataModelName := strcase.ToSnake(typeMapper.GetGenericNonePointerTypeNameByT[TDataModel]()) result := dbContext.DB().WithContext(ctx).First(&dataModel, id) if result.Error != nil { @@ -74,7 +74,7 @@ func FindModelByID[TDataModel interface{}, TModel interface{}]( func FindDataModelByID[TDataModel interface{}]( ctx context.Context, - dbContext contracts.IGormDBContext, + dbContext contracts.GormDBContext, id uuid.UUID, ) (TDataModel, error) { var dataModel TDataModel @@ -87,7 +87,7 @@ func FindDataModelByID[TDataModel interface{}]( // result := c.WithContext(ctx).First(&TDataModel{Id: id}) // result := c.WithContext(ctx).Scopes(scopes.FilterByID(id)).First(&dataModel) - dataModelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TDataModel]()) + dataModelName := strcase.ToSnake(typeMapper.GetGenericNonePointerTypeNameByT[TDataModel]()) result := dbContext.DB().WithContext(ctx).First(&dataModel, id) if result.Error != nil { @@ -109,12 +109,12 @@ func FindDataModelByID[TDataModel interface{}]( // DeleteDataModelByID delete the data-model inner a tx if exists func DeleteDataModelByID[TDataModel interface{}]( ctx context.Context, - dbContext contracts.IGormDBContext, + dbContext contracts.GormDBContext, id uuid.UUID, ) error { txDBContext := dbContext.WithTxIfExists(ctx) - dataModelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TDataModel]()) + dataModelName := strcase.ToSnake(typeMapper.GetGenericNonePointerTypeNameByT[TDataModel]()) exists := Exists[TDataModel](ctx, dbContext, id) if !exists { @@ -149,13 +149,13 @@ func DeleteDataModelByID[TDataModel interface{}]( // AddModel add the model inner a tx if exists func AddModel[TDataModel interface{}, TModel interface{}]( ctx context.Context, - dbContext contracts.IGormDBContext, + dbContext contracts.GormDBContext, model TModel, ) (TModel, error) { txDBContext := dbContext.WithTxIfExists(ctx) - dataModelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TDataModel]()) - modelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TModel]()) + dataModelName := strcase.ToSnake(typeMapper.GetGenericNonePointerTypeNameByT[TDataModel]()) + modelName := strcase.ToSnake(typeMapper.GetGenericNonePointerTypeNameByT[TModel]()) dataModel, err := mapper.Map[TDataModel](model) if err != nil { @@ -190,12 +190,12 @@ func AddModel[TDataModel interface{}, TModel interface{}]( // AddDataModel add the data-model inner a tx if exists func AddDataModel[TDataModel interface{}]( ctx context.Context, - dbContext contracts.IGormDBContext, + dbContext contracts.GormDBContext, dataModel TDataModel, ) (TDataModel, error) { txDBContext := dbContext.WithTxIfExists(ctx) - dataModelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TDataModel]()) + dataModelName := strcase.ToSnake(typeMapper.GetGenericNonePointerTypeNameByT[TDataModel]()) // https://gorm.io/docs/create.html result := txDBContext.DB().WithContext(ctx).Create(dataModel) @@ -214,13 +214,13 @@ func AddDataModel[TDataModel interface{}]( // UpdateModel update the model inner a tx if exists func UpdateModel[TDataModel interface{}, TModel interface{}]( ctx context.Context, - dbContext contracts.IGormDBContext, + dbContext contracts.GormDBContext, model TModel, ) (TModel, error) { txDBContext := dbContext.WithTxIfExists(ctx) - dataModelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TDataModel]()) - modelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TModel]()) + dataModelName := strcase.ToSnake(typeMapper.GetGenericNonePointerTypeNameByT[TDataModel]()) + modelName := strcase.ToSnake(typeMapper.GetGenericNonePointerTypeNameByT[TModel]()) dataModel, err := mapper.Map[TDataModel](model) if err != nil { @@ -255,12 +255,12 @@ func UpdateModel[TDataModel interface{}, TModel interface{}]( // UpdateDataModel update the data-model inner a tx if exists func UpdateDataModel[TDataModel interface{}]( ctx context.Context, - dbContext contracts.IGormDBContext, + dbContext contracts.GormDBContext, dataModel TDataModel, ) (TDataModel, error) { txDBContext := dbContext.WithTxIfExists(ctx) - dataModelName := strcase.ToSnake(typeMapper.GetNonePointerTypeNameByT[TDataModel]()) + dataModelName := strcase.ToSnake(typeMapper.GetGenericNonePointerTypeNameByT[TDataModel]()) // https://gorm.io/docs/update.html result := txDBContext.DB().WithContext(ctx).Updates(dataModel) diff --git a/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext_test.go b/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext_test.go index 3caf6212..354f4581 100644 --- a/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext_test.go +++ b/internal/pkg/postgresgorm/gormdbcontext/gorm_dbcontext_test.go @@ -65,7 +65,7 @@ type Product struct { type GormDBContextTestSuite struct { suite.Suite items []*ProductDataModel - dbContext contracts.IGormDBContext + dbContext contracts.GormDBContext app *fxtest.App dbFilePath string } @@ -217,7 +217,7 @@ func (s *GormDBContextTestSuite) SetupTest() { err := ConfigureProductsMappings() s.Require().NoError(err) - var gormDBContext contracts.IGormDBContext + var gormDBContext contracts.GormDBContext var gormOptions *gormPostgres.GormOptions app := fxtest.New( diff --git a/internal/pkg/postgresgorm/mediatr/pipelines/mediator_transaction_pipeline.go b/internal/pkg/postgresgorm/pipelines/mediator_transaction_pipeline.go similarity index 98% rename from internal/pkg/postgresgorm/mediatr/pipelines/mediator_transaction_pipeline.go rename to internal/pkg/postgresgorm/pipelines/mediator_transaction_pipeline.go index 7517f304..d8eb5863 100644 --- a/internal/pkg/postgresgorm/mediatr/pipelines/mediator_transaction_pipeline.go +++ b/internal/pkg/postgresgorm/pipelines/mediator_transaction_pipeline.go @@ -1,4 +1,4 @@ -package postgrespipelines +package pipelines import ( "context" diff --git a/internal/pkg/postgresgorm/repository/gorm_generic_repository.go b/internal/pkg/postgresgorm/repository/gorm_generic_repository.go index 8dee62a2..6526bf27 100644 --- a/internal/pkg/postgresgorm/repository/gorm_generic_repository.go +++ b/internal/pkg/postgresgorm/repository/gorm_generic_repository.go @@ -48,8 +48,8 @@ func (r *gormGenericRepository[TDataModel, TEntity]) Add( ctx context.Context, entity TEntity, ) error { - dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() - modelType := typeMapper.GetTypeFromGeneric[TEntity]() + dataModelType := typeMapper.GetGenericTypeByT[TDataModel]() + modelType := typeMapper.GetGenericTypeByT[TEntity]() if modelType == dataModelType { err := r.db.WithContext(ctx).Create(entity).Error @@ -95,8 +95,8 @@ func (r *gormGenericRepository[TDataModel, TEntity]) GetById( ctx context.Context, id uuid.UUID, ) (TEntity, error) { - dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() - modelType := typeMapper.GetTypeFromGeneric[TEntity]() + dataModelType := typeMapper.GetGenericTypeByT[TDataModel]() + modelType := typeMapper.GetGenericTypeByT[TEntity]() if modelType == dataModelType { var model TEntity @@ -161,7 +161,7 @@ func (r *gormGenericRepository[TDataModel, TEntity]) Search( listQuery *utils.ListQuery, ) (*utils.ListResult[TEntity], error) { fields := reflectionHelper.GetAllFields( - typeMapper.GetTypeFromGeneric[TDataModel](), + typeMapper.GetGenericTypeByT[TDataModel](), ) query := r.db @@ -192,8 +192,8 @@ func (r *gormGenericRepository[TDataModel, TEntity]) GetByFilter( ctx context.Context, filters map[string]interface{}, ) ([]TEntity, error) { - dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() - modelType := typeMapper.GetTypeFromGeneric[TEntity]() + dataModelType := typeMapper.GetGenericTypeByT[TDataModel]() + modelType := typeMapper.GetGenericTypeByT[TEntity]() if modelType == dataModelType { var models []TEntity err := r.db.WithContext(ctx).Where(filters).Find(&models).Error @@ -233,8 +233,8 @@ func (r *gormGenericRepository[TDataModel, TEntity]) Update( ctx context.Context, entity TEntity, ) error { - dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() - modelType := typeMapper.GetTypeFromGeneric[TEntity]() + dataModelType := typeMapper.GetGenericTypeByT[TDataModel]() + modelType := typeMapper.GetGenericTypeByT[TEntity]() if modelType == dataModelType { err := r.db.WithContext(ctx).Save(entity).Error if err != nil { @@ -295,8 +295,8 @@ func (r *gormGenericRepository[TDataModel, TEntity]) SkipTake( skip int, take int, ) ([]TEntity, error) { - dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() - modelType := typeMapper.GetTypeFromGeneric[TEntity]() + dataModelType := typeMapper.GetGenericTypeByT[TDataModel]() + modelType := typeMapper.GetGenericTypeByT[TEntity]() if modelType == dataModelType { var models []TEntity err := r.db.WithContext(ctx). @@ -335,8 +335,8 @@ func (r *gormGenericRepository[TDataModel, TEntity]) Find( ctx context.Context, specification specification.Specification, ) ([]TEntity, error) { - dataModelType := typeMapper.GetTypeFromGeneric[TDataModel]() - modelType := typeMapper.GetTypeFromGeneric[TEntity]() + dataModelType := typeMapper.GetGenericTypeByT[TDataModel]() + modelType := typeMapper.GetGenericTypeByT[TEntity]() if modelType == dataModelType { var models []TEntity err := r.db.WithContext(ctx). diff --git a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go b/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go index 9f340f1a..43da83a6 100644 --- a/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go +++ b/internal/pkg/postgresmessaging/messagepersistence/message_persistence_dbcontext.go @@ -1,47 +1,22 @@ package messagepersistence import ( - "context" - - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/helpers/gormextensions" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/contracts" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/gormdbcontext" "gorm.io/gorm" ) -type PostgresMessagePersistenceDBContextActionFunc func(ctx context.Context, messagePersistenceDBContext *PostgresMessagePersistenceDBContext) error - type PostgresMessagePersistenceDBContext struct { - *gorm.DB + // our dbcontext base + contracts.GormDBContext } func NewPostgresMessagePersistenceDBContext( db *gorm.DB, ) *PostgresMessagePersistenceDBContext { - c := &PostgresMessagePersistenceDBContext{DB: db} + // initialize base GormContext + c := &PostgresMessagePersistenceDBContext{GormDBContext: gormdbcontext.NewGormDBContext(db)} return c } - -// WithTx creates a transactional DBContext with getting tx-gorm from the ctx. This will throw an error if the transaction does not exist. -func (c *PostgresMessagePersistenceDBContext) WithTx( - ctx context.Context, -) (*PostgresMessagePersistenceDBContext, error) { - tx, err := gormextensions.GetTxFromContext(ctx) - if err != nil { - return nil, err - } - - return NewPostgresMessagePersistenceDBContext(tx), nil -} - -// WithTxIfExists creates a transactional DBContext with getting tx-gorm from the ctx. not throw an error if the transaction is not existing and returns an existing database. -func (c *PostgresMessagePersistenceDBContext) WithTxIfExists( - ctx context.Context, -) *PostgresMessagePersistenceDBContext { - tx := gormextensions.GetTxFromContextIfExists(ctx) - if tx == nil { - return c - } - - return NewPostgresMessagePersistenceDBContext(tx) -} diff --git a/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service.go b/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service.go index ab060fd6..6f535806 100644 --- a/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service.go +++ b/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service.go @@ -14,23 +14,23 @@ import ( uuid "github.com/satori/go.uuid" ) -type postgresMessageService struct { +type postgresMessagePersistenceService struct { messagingDBContext *PostgresMessagePersistenceDBContext messageSerializer contratcs.MessageSerializer logger logger.Logger } -func (m *postgresMessageService) Process(messageID string, ctx context.Context) error { +func (m *postgresMessagePersistenceService) Process(messageID string, ctx context.Context) error { // TODO implement me panic("implement me") } -func (m *postgresMessageService) ProcessAll(ctx context.Context) error { +func (m *postgresMessagePersistenceService) ProcessAll(ctx context.Context) error { // TODO implement me panic("implement me") } -func (m *postgresMessageService) AddPublishMessage( +func (m *postgresMessagePersistenceService) AddPublishMessage( messageEnvelope types.MessageEnvelopeTMessage, ctx context.Context, ) error { @@ -38,12 +38,15 @@ func (m *postgresMessageService) AddPublishMessage( panic("implement me") } -func (m *postgresMessageService) AddReceivedMessage(messageEnvelope types.MessageEnvelope, ctx context.Context) error { +func (m *postgresMessagePersistenceService) AddReceivedMessage( + messageEnvelope types.MessageEnvelope, + ctx context.Context, +) error { // TODO implement me panic("implement me") } -func (m *postgresMessageService) AddMessageCore( +func (m *postgresMessagePersistenceService) AddMessageCore( ctx context.Context, messageEnvelope types.MessageEnvelope, deliveryType persistmessage.MessageDeliveryType, @@ -96,14 +99,14 @@ func (m *postgresMessageService) AddMessageCore( func NewPostgresMessageService( postgresMessagePersistenceDBContext *PostgresMessagePersistenceDBContext, l logger.Logger, -) persistmessage.MessageService { - return &postgresMessageService{ +) persistmessage.MessagePersistenceService { + return &postgresMessagePersistenceService{ messagingDBContext: postgresMessagePersistenceDBContext, logger: l, } } -func (m *postgresMessageService) Add( +func (m *postgresMessagePersistenceService) Add( ctx context.Context, storeMessage *persistmessage.StoreMessage, ) error { @@ -123,7 +126,7 @@ func (m *postgresMessageService) Add( return nil } -func (m *postgresMessageService) Update( +func (m *postgresMessagePersistenceService) Update( ctx context.Context, storeMessage *persistmessage.StoreMessage, ) error { @@ -143,7 +146,7 @@ func (m *postgresMessageService) Update( return nil } -func (m *postgresMessageService) ChangeState( +func (m *postgresMessagePersistenceService) ChangeState( ctx context.Context, messageID uuid.UUID, status persistmessage.MessageStatus, @@ -165,7 +168,7 @@ func (m *postgresMessageService) ChangeState( return err } -func (m *postgresMessageService) GetAllActive( +func (m *postgresMessagePersistenceService) GetAllActive( ctx context.Context, ) ([]*persistmessage.StoreMessage, error) { var storeMessages []*persistmessage.StoreMessage @@ -183,7 +186,7 @@ func (m *postgresMessageService) GetAllActive( return storeMessages, nil } -func (m *postgresMessageService) GetByFilter( +func (m *postgresMessagePersistenceService) GetByFilter( ctx context.Context, predicate func(*persistmessage.StoreMessage) bool, ) ([]*persistmessage.StoreMessage, error) { @@ -199,7 +202,7 @@ func (m *postgresMessageService) GetByFilter( return storeMessages, nil } -func (m *postgresMessageService) GetById( +func (m *postgresMessagePersistenceService) GetById( ctx context.Context, id uuid.UUID, ) (*persistmessage.StoreMessage, error) { @@ -226,7 +229,7 @@ func (m *postgresMessageService) GetById( return storeMessage, nil } -func (m *postgresMessageService) Remove( +func (m *postgresMessagePersistenceService) Remove( ctx context.Context, storeMessage *persistmessage.StoreMessage, ) (bool, error) { @@ -261,7 +264,7 @@ func (m *postgresMessageService) Remove( return true, nil } -func (m *postgresMessageService) CleanupMessages( +func (m *postgresMessagePersistenceService) CleanupMessages( ctx context.Context, ) error { predicate := func(sm *persistmessage.StoreMessage) bool { diff --git a/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service_test.go b/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service_test.go index 3bb4a967..f9da304c 100644 --- a/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service_test.go +++ b/internal/pkg/postgresmessaging/messagepersistence/postgres_message_service_test.go @@ -11,6 +11,7 @@ import ( "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/config/environment" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/messaging/persistmessage" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" defaultLogger "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger/defaultlogger" @@ -32,7 +33,7 @@ type postgresMessageServiceTest struct { suite.Suite DB *gorm.DB logger logger.Logger - messagingRepository persistmessage.MessageService + messagingRepository persistmessage.MessagePersistenceService dbContext *PostgresMessagePersistenceDBContext storeMessages []*persistmessage.StoreMessage ctx context.Context @@ -75,6 +76,7 @@ func (c *postgresMessageServiceTest) SetupTest() { config.ModuleFunc(environment.Test), zap.Module, fxlog.FxLogger, + core.Module, postgresgorm.Module, fx.Decorate( func(cfg *postgresgorm.GormOptions) (*postgresgorm.GormOptions, error) { @@ -105,27 +107,6 @@ func (c *postgresMessageServiceTest) TearDownTest() { c.app.RequireStop() } -func (c *postgresMessageServiceTest) initDB() { - err := migrateGorm(c.dbContext.DB) - c.Require().NoError(err) - - storeMessages, err := seedData(c.dbContext.DB) - c.Require().NoError(err) - - c.storeMessages = storeMessages -} - -func (c *postgresMessageServiceTest) cleanupDB() error { - sqldb, _ := c.dbContext.DB.DB() - e := sqldb.Close() - c.Require().NoError(e) - - // removing sql-lite file - err := os.Remove(s.dbFilePath) - - return err -} - //func (c *postgresMessageServiceTest) SetupTest() { // ctx := context.Background() // c.ctx = ctx @@ -141,7 +122,7 @@ func (c *postgresMessageServiceTest) cleanupDB() error { func (c *postgresMessageServiceTest) BeginTx() { c.logger.Info("starting transaction") - tx := c.dbContext.Begin() + tx := c.dbContext.DB().Begin() gormContext := gormextensions.SetTxToContext(c.ctx, tx) c.ctx = gormContext } @@ -179,6 +160,27 @@ func (c *postgresMessageServiceTest) Test_Add() { c.Assert().Equal(message.ID, m.ID) } +func (c *postgresMessageServiceTest) initDB() { + err := migrateGorm(c.dbContext.DB()) + c.Require().NoError(err) + + storeMessages, err := seedData(c.dbContext.DB()) + c.Require().NoError(err) + + c.storeMessages = storeMessages +} + +func (c *postgresMessageServiceTest) cleanupDB() error { + sqldb, _ := c.dbContext.DB().DB() + e := sqldb.Close() + c.Require().NoError(e) + + // removing sql-lite file + err := os.Remove(c.dbFilePath) + + return err +} + func migrateGorm(db *gorm.DB) error { err := db.AutoMigrate(&persistmessage.StoreMessage{}) if err != nil { diff --git a/internal/pkg/postgrespgx/postgres_pgx_options.go b/internal/pkg/postgrespgx/postgres_pgx_options.go index 9c19f9f7..61d6dcd4 100644 --- a/internal/pkg/postgrespgx/postgres_pgx_options.go +++ b/internal/pkg/postgrespgx/postgres_pgx_options.go @@ -8,7 +8,7 @@ import ( "github.com/iancoleman/strcase" ) -var optionName = strcase.ToLowerCamel(typeMapper.GetTypeNameByT[PostgresPgxOptions]()) +var optionName = strcase.ToLowerCamel(typeMapper.GetGenericTypeNameByT[PostgresPgxOptions]()) type PostgresPgxOptions struct { Host string `mapstructure:"host"` diff --git a/internal/pkg/postgressqlx/postgres_sqlx_options.go b/internal/pkg/postgressqlx/postgres_sqlx_options.go index eaf53b12..4794790f 100644 --- a/internal/pkg/postgressqlx/postgres_sqlx_options.go +++ b/internal/pkg/postgressqlx/postgres_sqlx_options.go @@ -8,7 +8,7 @@ import ( "github.com/iancoleman/strcase" ) -var optionName = strcase.ToLowerCamel(typeMapper.GetTypeNameByT[PostgresSqlxOptions]()) +var optionName = strcase.ToLowerCamel(typeMapper.GetGenericTypeNameByT[PostgresSqlxOptions]()) type PostgresSqlxOptions struct { Host string `mapstructure:"host"` diff --git a/internal/pkg/rabbitmq/config/rabbitmq_options.go b/internal/pkg/rabbitmq/config/rabbitmq_options.go index 50c99ba6..25cbaaee 100644 --- a/internal/pkg/rabbitmq/config/rabbitmq_options.go +++ b/internal/pkg/rabbitmq/config/rabbitmq_options.go @@ -39,7 +39,7 @@ func (h *RabbitmqHostOptions) HttpEndPoint() string { } func ProvideConfig(environment environment.Environment) (*RabbitmqOptions, error) { - optionName := strcase.ToLowerCamel(typeMapper.GetTypeNameByT[RabbitmqOptions]()) + optionName := strcase.ToLowerCamel(typeMapper.GetGenericTypeNameByT[RabbitmqOptions]()) cfg, err := config.BindConfigKey[*RabbitmqOptions](optionName, environment) return cfg, err diff --git a/internal/pkg/redis/redis_options.go b/internal/pkg/redis/redis_options.go index 3e35fe2e..077a92a6 100644 --- a/internal/pkg/redis/redis_options.go +++ b/internal/pkg/redis/redis_options.go @@ -8,7 +8,7 @@ import ( "github.com/iancoleman/strcase" ) -var optionName = strcase.ToLowerCamel(typeMapper.GetTypeNameByT[RedisOptions]()) +var optionName = strcase.ToLowerCamel(typeMapper.GetGenericTypeNameByT[RedisOptions]()) type RedisOptions struct { Host string `mapstructure:"host"` diff --git a/internal/pkg/reflection/reflectionhelper/reflection_helper_test.go b/internal/pkg/reflection/reflectionhelper/reflection_helper_test.go index e2b13bac..48183139 100644 --- a/internal/pkg/reflection/reflectionhelper/reflection_helper_test.go +++ b/internal/pkg/reflection/reflectionhelper/reflection_helper_test.go @@ -101,7 +101,7 @@ func Test_Get_Field_Value_For_Exported_Fields_And_Addressable_Struct(t *testing. // field by name only work on struct not pointer type so we should get Elem() v := reflect.ValueOf(p).Elem() - name := GetFieldValue(v.FieldByName("Name")).Interface() + name := GetFieldValue(v.FieldByName("ShortTypeName")).Interface() age := GetFieldValue(v.FieldByName("Age")).Interface() assert.Equal(t, "John", name) @@ -125,7 +125,7 @@ func Test_Get_Field_Value_For_Exported_Fields_And_UnAddressable_Struct(t *testin // field by name only work on struct not pointer type so we should get Elem() v := reflect.ValueOf(&p).Elem() - name := GetFieldValue(v.FieldByName("Name")).Interface() + name := GetFieldValue(v.FieldByName("ShortTypeName")).Interface() age := GetFieldValue(v.FieldByName("Age")).Interface() assert.Equal(t, "John", name) @@ -149,7 +149,7 @@ func Test_Set_Field_For_Exported_Fields_And_Addressable_Struct(t *testing.T) { // field by name only work on struct not pointer type so we should get Elem() v := reflect.ValueOf(p).Elem() - name := GetFieldValue(v.FieldByName("Name")) + name := GetFieldValue(v.FieldByName("ShortTypeName")) age := GetFieldValue(v.FieldByName("Age")) SetFieldValue(name, "John") @@ -179,7 +179,7 @@ func Test_Set_Field_For_Exported_Fields_And_UnAddressable_Struct(t *testing.T) { // field by name only work on struct not pointer type so we should get Elem() v := reflect.ValueOf(&p).Elem() - name := GetFieldValue(v.FieldByName("Name")) + name := GetFieldValue(v.FieldByName("ShortTypeName")) age := GetFieldValue(v.FieldByName("Age")) SetFieldValue(name, "John") @@ -206,14 +206,14 @@ func Test_Set_Field_For_UnExported_Fields_And_UnAddressable_Struct(t *testing.T) func Test_Get_Unexported_Field_From_Method_And_Addressable_Struct(t *testing.T) { p := &PersonPrivate{name: "John", age: 20} - name := GetFieldValueFromMethodAndObject(p, "Name") + name := GetFieldValueFromMethodAndObject(p, "ShortTypeName") assert.Equal(t, "John", name.Interface()) } func Test_Get_Unexported_Field_From_Method_And_UnAddressable_Struct(t *testing.T) { p := PersonPrivate{name: "John", age: 20} - name := GetFieldValueFromMethodAndObject(p, "Name") + name := GetFieldValueFromMethodAndObject(p, "ShortTypeName") assert.Equal(t, "John", name.Interface()) } @@ -224,7 +224,7 @@ func Test_Convert_NoPointer_Type_To_Pointer_Type_With_Addr(t *testing.T) { p := PersonPrivate{name: "John", age: 20} v := reflect.ValueOf(&p).Elem() pointerType := v.Addr() - name := pointerType.MethodByName("Name").Call(nil)[0].Interface() + name := pointerType.MethodByName("ShortTypeName").Call(nil)[0].Interface() age := pointerType.MethodByName("Age").Call(nil)[0].Interface() assert.Equal(t, "John", name) diff --git a/internal/pkg/reflection/typemapper/type_mapper.go b/internal/pkg/reflection/typemapper/type_mapper.go index f35ef4a3..89fae6b4 100644 --- a/internal/pkg/reflection/typemapper/type_mapper.go +++ b/internal/pkg/reflection/typemapper/type_mapper.go @@ -112,7 +112,7 @@ func TypeByNameAndImplementedInterface[TInterface interface{}]( typeName string, ) reflect.Type { // https://stackoverflow.com/questions/7132848/how-to-get-the-reflect-type-of-an-interface - implementedInterface := GetTypeFromGeneric[TInterface]() + implementedInterface := GetGenericTypeByT[TInterface]() if types, ok := types[typeName]; ok { for _, t := range types { if t.Implements(implementedInterface) { @@ -128,7 +128,7 @@ func TypesImplementedInterfaceWithFilterTypes[TInterface interface{}]( types []reflect.Type, ) []reflect.Type { // https://stackoverflow.com/questions/7132848/how-to-get-the-reflect-type-of-an-interface - implementedInterface := GetTypeFromGeneric[TInterface]() + implementedInterface := GetGenericTypeByT[TInterface]() var res []reflect.Type for _, t := range types { @@ -142,7 +142,7 @@ func TypesImplementedInterfaceWithFilterTypes[TInterface interface{}]( func TypesImplementedInterface[TInterface interface{}]() []reflect.Type { // https://stackoverflow.com/questions/7132848/how-to-get-the-reflect-type-of-an-interface - implementedInterface := GetTypeFromGeneric[TInterface]() + implementedInterface := GetGenericTypeByT[TInterface]() var res []reflect.Type for _, t := range types { @@ -166,6 +166,12 @@ func GetFullTypeName(input interface{}) string { return t.String() } +func GetGenericFullTypeNameByT[T any]() string { + t := reflect.TypeOf((*T)(nil)).Elem() + + return t.String() +} + func GetFullTypeNameByType(typ reflect.Type) string { return typ.String() } @@ -210,7 +216,7 @@ func GetKebabTypeName(input interface{}) string { return strcase.ToKebab(t.Elem().Name()) } -func GetTypeNameByT[T any]() string { +func GetGenericTypeNameByT[T any]() string { t := reflect.TypeOf((*T)(nil)).Elem() if t.Kind() != reflect.Ptr { return t.Name() @@ -219,7 +225,7 @@ func GetTypeNameByT[T any]() string { return fmt.Sprintf("*%s", t.Elem().Name()) } -func GetNonePointerTypeNameByT[T any]() string { +func GetGenericNonePointerTypeNameByT[T any]() string { t := reflect.TypeOf((*T)(nil)).Elem() if t.Kind() != reflect.Ptr { return t.Name() @@ -282,7 +288,7 @@ func TypesByPackageName(pkgPath string, name string) []reflect.Type { return nil } -func GetTypeFromGeneric[T interface{}]() reflect.Type { +func GetGenericTypeByT[T interface{}]() reflect.Type { res := reflect.TypeOf((*T)(nil)).Elem() return res } @@ -315,7 +321,7 @@ func GetBaseReflectType(value interface{}) reflect.Type { func GenericInstanceByT[T any]() T { // https://stackoverflow.com/questions/7132848/how-to-get-the-reflect-type-of-an-interface - typ := GetTypeFromGeneric[T]() + typ := GetGenericTypeByT[T]() return getInstanceFromType(typ).(T) } @@ -381,7 +387,7 @@ func getInstanceFromType(typ reflect.Type) interface{} { // return reflect.New(typ).Elem().Interface() } -func GetImplementInterfaceTypes[T any]() map[string][]reflect.Type { +func GetGenericImplementInterfaceTypesT[T any]() map[string][]reflect.Type { result := make(map[string][]reflect.Type) // Get the interface type @@ -406,3 +412,14 @@ func GetImplementInterfaceTypes[T any]() map[string][]reflect.Type { return result } + +func ImplementedInterfaceT[T any](obj interface{}) bool { + // Get the interface type + interfaceType := reflect.TypeOf((*T)(nil)).Elem() + + typ := GetReflectType(obj) + + implemented := typ.Implements(interfaceType) + + return implemented +} diff --git a/internal/pkg/reflection/typemapper/type_mapper_test.go b/internal/pkg/reflection/typemapper/type_mapper_test.go index 5a372fef..b2066fdb 100644 --- a/internal/pkg/reflection/typemapper/type_mapper_test.go +++ b/internal/pkg/reflection/typemapper/type_mapper_test.go @@ -11,24 +11,24 @@ import ( ) func Test_GetTypeNameByT(t *testing.T) { - pointerTypeName := GetTypeNameByT[*Test]() - nonePointerTypeName := GetTypeNameByT[Test]() + pointerTypeName := GetGenericTypeNameByT[*Test]() + nonePointerTypeName := GetGenericTypeNameByT[Test]() require.Equal(t, pointerTypeName, "*Test") require.Equal(t, nonePointerTypeName, "Test") } func Test_GetNonePointerTypeNameByT(t *testing.T) { - pointerTypeName := GetNonePointerTypeNameByT[*Test]() - nonePointerTypeName := GetNonePointerTypeNameByT[Test]() + pointerTypeName := GetGenericNonePointerTypeNameByT[*Test]() + nonePointerTypeName := GetGenericNonePointerTypeNameByT[Test]() require.Equal(t, pointerTypeName, "Test") require.Equal(t, nonePointerTypeName, "Test") } func Test_TypeByName(t *testing.T) { - s1 := TypeByName("*typeMapper.Test") - s2 := TypeByName("typeMapper.Test") + s1 := TypeByName("*typemapper.Test") + s2 := TypeByName("typemapper.Test") s3 := TypeByName("*Test") s4 := TypeByName("Test") @@ -55,18 +55,22 @@ func Test_GetFullTypeName(t *testing.T) { typeName1 := GetFullTypeName(t1) typeName2 := GetFullTypeName(t2) + typeName3 := GetGenericFullTypeNameByT[*Test]() + typeName4 := GetGenericFullTypeNameByT[Test]() - assert.Equal(t, "typeMapper.Test", typeName1) - assert.Equal(t, "*typeMapper.Test", typeName2) + assert.Equal(t, "typemapper.Test", typeName1) + assert.Equal(t, "*typemapper.Test", typeName2) + assert.Equal(t, "*typemapper.Test", typeName3) + assert.Equal(t, "typemapper.Test", typeName4) } func Test_InstanceByTypeName(t *testing.T) { - s1 := InstanceByTypeName("typeMapper.Test").(Test) + s1 := InstanceByTypeName("typemapper.Test").(Test) s1.A = 100 assert.NotNil(t, s1) assert.NotZero(t, s1.A) - s2 := InstanceByTypeName("*typeMapper.Test").(*Test) + s2 := InstanceByTypeName("*typemapper.Test").(*Test) s2.A = 100 assert.NotNil(t, s2) assert.NotZero(t, s2.A) @@ -79,8 +83,8 @@ func Test_InstanceByTypeName(t *testing.T) { } func Test_InstancePointerByTypeName(t *testing.T) { - s1 := InstancePointerByTypeName("*typeMapper.Test").(*Test) - s2 := InstancePointerByTypeName("typeMapper.Test").(*Test) + s1 := InstancePointerByTypeName("*typemapper.Test").(*Test) + s2 := InstancePointerByTypeName("typemapper.Test").(*Test) s3 := InstancePointerByTypeName("*Test").(*Test) s4 := InstancePointerByTypeName("Test").(*Test) @@ -91,9 +95,9 @@ func Test_InstancePointerByTypeName(t *testing.T) { } func Test_GetTypeFromGeneric(t *testing.T) { - s1 := GetTypeFromGeneric[Test]() - s2 := GetTypeFromGeneric[*Test]() - s3 := GetTypeFromGeneric[ITest]() + s1 := GetGenericTypeByT[Test]() + s2 := GetGenericTypeByT[*Test]() + s3 := GetGenericTypeByT[ITest]() assert.NotNil(t, s1) assert.NotNil(t, s2) @@ -109,13 +113,13 @@ func Test_GenericInstanceByT(t *testing.T) { } func Test_TypeByNameAndImplementedInterface(t *testing.T) { - s1 := TypeByNameAndImplementedInterface[ITest]("*typeMapper.Test") + s1 := TypeByNameAndImplementedInterface[ITest]("*typemapper.Test") assert.NotNil(t, s1) } func Test_EmptyInstanceByTypeNameAndImplementedInterface(t *testing.T) { - s1 := EmptyInstanceByTypeNameAndImplementedInterface[ITest]("*typeMapper.Test") + s1 := EmptyInstanceByTypeNameAndImplementedInterface[ITest]("*typemapper.Test") assert.NotNil(t, s1) } diff --git a/internal/pkg/utils/errorutils/errors.go b/internal/pkg/utils/errorutils/errors.go index 0ee26503..18229d13 100644 --- a/internal/pkg/utils/errorutils/errors.go +++ b/internal/pkg/utils/errorutils/errors.go @@ -24,7 +24,7 @@ func CheckErrMessages(err error, messages ...string) bool { return false } -// ErrorsWithStack returns a string contains grpc_errors messages in the stack with its stack trace levels for given error +// ErrorsWithStack returns a string contains errors messages in the stack with its stack trace levels for given error func ErrorsWithStack(err error) string { res := fmt.Sprintf("%+v\n", err) return res diff --git a/internal/pkg/validation/pipeline/validation_pipeline.go b/internal/pkg/validation/pipeline/validation_pipeline.go index 5ea3d440..a8ab86c5 100644 --- a/internal/pkg/validation/pipeline/validation_pipeline.go +++ b/internal/pkg/validation/pipeline/validation_pipeline.go @@ -3,7 +3,6 @@ package pipeline import ( "context" - customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/logger" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/validation" @@ -27,9 +26,7 @@ func (m mediatorValidationPipeline) Handle( if ok { err := v.Validate() if err != nil { - validationErr := customErrors.NewValidationErrorWrap(err, "validation failed") - - return nil, validationErr + return nil, err } } diff --git a/internal/services/catalogreadservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go b/internal/services/catalogreadservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go index 7538d61b..da5f2fed 100644 --- a/internal/services/catalogreadservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go +++ b/internal/services/catalogreadservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go @@ -8,7 +8,7 @@ import ( metricspipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/mediatr/pipelines" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" tracingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/mediatr/pipelines" - postgrespipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/mediatr/pipelines" + postgrespipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/pipelines" "github.com/mehdihadeli/go-mediatr" "gorm.io/gorm" diff --git a/internal/services/catalogwriteservice/config/app_options.go b/internal/services/catalogwriteservice/config/app_options.go index 0823bbe3..137534c0 100644 --- a/internal/services/catalogwriteservice/config/app_options.go +++ b/internal/services/catalogwriteservice/config/app_options.go @@ -16,7 +16,7 @@ type AppOptions struct { } func NewAppOptions(environment environment.Environment) (*AppOptions, error) { - optionName := strcase.ToLowerCamel(typeMapper.GetTypeNameByT[AppOptions]()) + optionName := strcase.ToLowerCamel(typeMapper.GetGenericTypeNameByT[AppOptions]()) cfg, err := config.BindConfigKey[*AppOptions](optionName, environment) if err != nil { return nil, err diff --git a/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product.go b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product.go index 34c4802d..f5d977ae 100644 --- a/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product.go +++ b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product.go @@ -3,6 +3,9 @@ package v1 import ( "time" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" + validation "github.com/go-ozzo/ozzo-validation" uuid "github.com/satori/go.uuid" ) @@ -11,6 +14,7 @@ import ( // https://github.com/go-playground/validator type CreateProduct struct { + cqrs.Command ProductID uuid.UUID Name string Description string @@ -18,33 +22,42 @@ type CreateProduct struct { CreatedAt time.Time } +// NewCreateProduct Create a new product func NewCreateProduct( name string, description string, price float64, -) (*CreateProduct, error) { +) *CreateProduct { command := &CreateProduct{ + Command: cqrs.NewCommandByT[CreateProduct](), ProductID: uuid.NewV4(), Name: name, Description: description, Price: price, CreatedAt: time.Now(), } + + return command +} + +// NewCreateProductWithValidation Create a new product with inline validation - for defensive programming and ensuring validation even without using middleware +func NewCreateProductWithValidation( + name string, + description string, + price float64, +) (*CreateProduct, error) { + command := NewCreateProduct(name, description, price) err := command.Validate() - if err != nil { - return nil, err - } - return command, nil + return command, err } -// IsTxRequest for enabling transactions on the mediatr pipeline func (c *CreateProduct) IsTxRequest() bool { return true } func (c *CreateProduct) Validate() error { - return validation.ValidateStruct( + err := validation.ValidateStruct( c, validation.Field(&c.ProductID, validation.Required), validation.Field( @@ -64,4 +77,9 @@ func (c *CreateProduct) Validate() error { ), validation.Field(&c.CreatedAt, validation.Required), ) + if err != nil { + return customErrors.NewValidationErrorWrap(err, "validation error") + } + + return nil } diff --git a/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product_endpoint.go b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product_endpoint.go index e5328a11..41ec53a0 100644 --- a/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product_endpoint.go +++ b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product_endpoint.go @@ -50,18 +50,13 @@ func (ep *createProductEndpoint) handler() echo.HandlerFunc { return badRequestErr } - command, err := NewCreateProduct( + command, err := NewCreateProductWithValidation( request.Name, request.Description, request.Price, ) if err != nil { - validationErr := customErrors.NewValidationErrorWrap( - err, - "command validation failed", - ) - - return validationErr + return err } result, err := mediatr.Send[*CreateProduct, *dtos.CreateProductResponseDto]( diff --git a/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product.go b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product.go index c178ab7e..5debf93b 100644 --- a/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product.go +++ b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product.go @@ -1,6 +1,8 @@ package v1 import ( + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" + validation "github.com/go-ozzo/ozzo-validation" "github.com/go-ozzo/ozzo-validation/is" uuid "github.com/satori/go.uuid" @@ -10,14 +12,19 @@ type DeleteProduct struct { ProductID uuid.UUID } -func NewDeleteProduct(productID uuid.UUID) (*DeleteProduct, error) { +// NewDeleteProduct delete a product +func NewDeleteProduct(productID uuid.UUID) *DeleteProduct { command := &DeleteProduct{ProductID: productID} + + return command +} + +// NewDeleteProductWithValidation delete a product with inline validation - for defensive programming and ensuring validation even without using middleware +func NewDeleteProductWithValidation(productID uuid.UUID) (*DeleteProduct, error) { + command := NewDeleteProduct(productID) err := command.Validate() - if err != nil { - return nil, err - } - return command, nil + return command, err } // IsTxRequest for enabling transactions on the mediatr pipeline @@ -25,10 +32,15 @@ func (c *DeleteProduct) IsTxRequest() bool { return true } -func (p *DeleteProduct) Validate() error { - return validation.ValidateStruct( - p, - validation.Field(&p.ProductID, validation.Required), - validation.Field(&p.ProductID, is.UUIDv4), +func (c *DeleteProduct) Validate() error { + err := validation.ValidateStruct( + c, + validation.Field(&c.ProductID, validation.Required), + validation.Field(&c.ProductID, is.UUIDv4), ) + if err != nil { + return customErrors.NewValidationErrorWrap(err, "validation error") + } + + return nil } diff --git a/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_endpoint.go b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_endpoint.go index 20ea8e86..74b036da 100644 --- a/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_endpoint.go +++ b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_endpoint.go @@ -50,14 +50,9 @@ func (ep *deleteProductEndpoint) handler() echo.HandlerFunc { return badRequestErr } - command, err := NewDeleteProduct(request.ProductID) + command, err := NewDeleteProductWithValidation(request.ProductID) if err != nil { - validationErr := customErrors.NewValidationErrorWrap( - err, - "command validation failed", - ) - - return validationErr + return err } _, err = mediatr.Send[*DeleteProduct, *mediatr.Unit]( diff --git a/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id.go b/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id.go index 27884819..f88a07f3 100644 --- a/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id.go +++ b/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id.go @@ -1,6 +1,9 @@ package v1 import ( + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" + validation "github.com/go-ozzo/ozzo-validation" "github.com/go-ozzo/ozzo-validation/is" uuid "github.com/satori/go.uuid" @@ -10,22 +13,34 @@ import ( // https://github.com/go-playground/validator type GetProductById struct { + cqrs.Query ProductID uuid.UUID } -func NewGetProductById(productId uuid.UUID) (*GetProductById, error) { - query := &GetProductById{ProductID: productId} - err := query.Validate() - if err != nil { - return nil, err +func NewGetProductById(productId uuid.UUID) *GetProductById { + query := &GetProductById{ + Query: cqrs.NewQueryByT[GetProductById](), + ProductID: productId, } - return query, nil + return query +} + +func NewGetProductByIdWithValidation(productId uuid.UUID) (*GetProductById, error) { + query := NewGetProductById(productId) + err := query.Validate() + + return query, err } func (p *GetProductById) Validate() error { - return validation.ValidateStruct( + err := validation.ValidateStruct( p, validation.Field(&p.ProductID, validation.Required, is.UUIDv4), ) + if err != nil { + return customErrors.NewValidationErrorWrap(err, "validation error") + } + + return nil } diff --git a/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id_endpoint.go b/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id_endpoint.go index da25eeff..450f6682 100644 --- a/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id_endpoint.go +++ b/internal/services/catalogwriteservice/internal/products/features/gettingproductbyid/v1/get_product_by_id_endpoint.go @@ -50,14 +50,9 @@ func (ep *getProductByIdEndpoint) handler() echo.HandlerFunc { return badRequestErr } - query, err := NewGetProductById(request.ProductId) + query, err := NewGetProductByIdWithValidation(request.ProductId) if err != nil { - validationErr := customErrors.NewValidationErrorWrap( - err, - "query validation failed", - ) - - return validationErr + return err } queryResult, err := mediatr.Send[*GetProductById, *dtos.GetProductByIdResponseDto]( diff --git a/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products.go b/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products.go index 60a12ac2..b32647c8 100644 --- a/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products.go +++ b/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products.go @@ -1,6 +1,7 @@ package v1 import ( + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/utils" validation "github.com/go-ozzo/ozzo-validation" @@ -11,20 +12,28 @@ type SearchProducts struct { *utils.ListQuery } -func NewSearchProducts(searchText string, query *utils.ListQuery) (*SearchProducts, error) { - command := &SearchProducts{ +func NewSearchProducts(searchText string, query *utils.ListQuery) *SearchProducts { + searchProductQuery := &SearchProducts{ SearchText: searchText, ListQuery: query, } - err := command.Validate() - if err != nil { - return nil, err - } + return searchProductQuery +} + +func NewSearchProductsWithValidation(searchText string, query *utils.ListQuery) (*SearchProducts, error) { + searchProductQuery := NewSearchProducts(searchText, query) - return command, nil + err := searchProductQuery.Validate() + + return searchProductQuery, err } func (p *SearchProducts) Validate() error { - return validation.ValidateStruct(p, validation.Field(&p.SearchText, validation.Required)) + err := validation.ValidateStruct(p, validation.Field(&p.SearchText, validation.Required)) + if err != nil { + return customErrors.NewValidationErrorWrap(err, "validation error") + } + + return nil } diff --git a/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_endpoint.go b/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_endpoint.go index e4db7d5d..efd9ad54 100644 --- a/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_endpoint.go +++ b/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_endpoint.go @@ -61,17 +61,12 @@ func (ep *searchProductsEndpoint) handler() echo.HandlerFunc { return badRequestErr } - query, err := NewSearchProducts( + query, err := NewSearchProductsWithValidation( request.SearchText, request.ListQuery, ) if err != nil { - validationErr := customErrors.NewValidationErrorWrap( - err, - "query validation failed", - ) - - return validationErr + return err } queryResult, err := mediatr.Send[*SearchProducts, *dtos.SearchProductsResponseDto]( diff --git a/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_handler.go b/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_handler.go index ee63478a..f251cf01 100644 --- a/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_handler.go +++ b/internal/services/catalogwriteservice/internal/products/features/searchingproduct/v1/search_products_handler.go @@ -78,7 +78,7 @@ func (c *searchProductsHandler) prepareSearchDBQuery( query *SearchProducts, ) *gorm.DB { fields := reflectionHelper.GetAllFields( - typeMapper.GetTypeFromGeneric[*datamodel.ProductDataModel](), + typeMapper.GetGenericTypeByT[*datamodel.ProductDataModel](), ) dbQuery := c.CatalogsDBContext.DB() diff --git a/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product.go b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product.go index a55072a0..fc021d3b 100644 --- a/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product.go +++ b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product.go @@ -3,6 +3,8 @@ package v1 import ( "time" + customErrors "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/http/httperrors/customerrors" + validation "github.com/go-ozzo/ozzo-validation" uuid "github.com/satori/go.uuid" ) @@ -20,7 +22,7 @@ func NewUpdateProduct( name string, description string, price float64, -) (*UpdateProduct, error) { +) *UpdateProduct { command := &UpdateProduct{ ProductID: productID, Name: name, @@ -28,12 +30,20 @@ func NewUpdateProduct( Price: price, UpdatedAt: time.Now(), } + + return command +} + +func NewUpdateProductWithValidation( + productID uuid.UUID, + name string, + description string, + price float64, +) (*UpdateProduct, error) { + command := NewUpdateProduct(productID, name, description, price) err := command.Validate() - if err != nil { - return nil, err - } - return command, nil + return command, err } // IsTxRequest for enabling transactions on the mediatr pipeline @@ -41,21 +51,26 @@ func (c *UpdateProduct) IsTxRequest() bool { return true } -func (p *UpdateProduct) Validate() error { - return validation.ValidateStruct( - p, - validation.Field(&p.ProductID, validation.Required), +func (c *UpdateProduct) Validate() error { + err := validation.ValidateStruct( + c, + validation.Field(&c.ProductID, validation.Required), validation.Field( - &p.Name, + &c.Name, validation.Required, validation.Length(0, 255), ), validation.Field( - &p.Description, + &c.Description, validation.Required, validation.Length(0, 5000), ), - validation.Field(&p.Price, validation.Required, validation.Min(0.0)), - validation.Field(&p.UpdatedAt, validation.Required), + validation.Field(&c.Price, validation.Required, validation.Min(0.0)), + validation.Field(&c.UpdatedAt, validation.Required), ) + if err != nil { + return customErrors.NewValidationErrorWrap(err, "validation error") + } + + return nil } diff --git a/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_endpoint.go b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_endpoint.go index f036de7b..5e93a64e 100644 --- a/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_endpoint.go +++ b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_endpoint.go @@ -51,19 +51,14 @@ func (ep *updateProductEndpoint) handler() echo.HandlerFunc { return badRequestErr } - command, err := NewUpdateProduct( + command, err := NewUpdateProductWithValidation( request.ProductID, request.Name, request.Description, request.Price, ) if err != nil { - validationErr := customErrors.NewValidationErrorWrap( - err, - "command validation failed", - ) - - return validationErr + return err } _, err = mediatr.Send[*UpdateProduct, *mediatr.Unit]( diff --git a/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go b/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go index 29923b2e..60ad6c9b 100644 --- a/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go +++ b/internal/services/catalogwriteservice/internal/shared/configurations/catalogs/infrastructure/infrastructure_configurator.go @@ -8,7 +8,8 @@ import ( metricspipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/metrics/mediatr/pipelines" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing" tracingpipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/otel/tracing/mediatr/pipelines" - postgrespipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/mediatr/pipelines" + postgrespipelines "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/pipelines" + validationpieline "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/validation/pipeline" "github.com/mehdihadeli/go-mediatr" "gorm.io/gorm" @@ -31,6 +32,7 @@ func (ic *InfrastructureConfigurator) ConfigInfrastructures() { func(l logger.Logger, tracer tracing.AppTracer, metrics metrics.AppMetrics, db *gorm.DB) error { err := mediatr.RegisterRequestPipelineBehaviors( loggingpipelines.NewMediatorLoggingPipeline(l), + validationpieline.NewMediatorValidationPipeline(l), tracingpipelines.NewMediatorTracingPipeline( tracer, tracingpipelines.WithLogger(l), diff --git a/internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext.go b/internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext.go index 8417e43e..075eea51 100644 --- a/internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext.go +++ b/internal/services/catalogwriteservice/internal/shared/data/dbcontext/catalogs_dbcontext.go @@ -1,24 +1,20 @@ package dbcontext import ( - "context" - "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/contracts" "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/postgresgorm/gormdbcontext" "gorm.io/gorm" ) -type CatalogContextActionFunc func(ctx context.Context, catalogContext *CatalogsGormDBContext) error - type CatalogsGormDBContext struct { // our dbcontext base - contracts.IGormDBContext + contracts.GormDBContext } func NewCatalogsDBContext(db *gorm.DB) *CatalogsGormDBContext { - // initialize base - c := &CatalogsGormDBContext{IGormDBContext: gormdbcontext.NewGormDBContext(db)} + // initialize base GormContext + c := &CatalogsGormDBContext{GormDBContext: gormdbcontext.NewGormDBContext(db)} return c } diff --git a/internal/services/catalogwriteservice/internal/shared/grpc/genproto/products.pb.go b/internal/services/catalogwriteservice/internal/shared/grpc/genproto/products.pb.go index 7129f4a8..579f3c31 100644 --- a/internal/services/catalogwriteservice/internal/shared/grpc/genproto/products.pb.go +++ b/internal/services/catalogwriteservice/internal/shared/grpc/genproto/products.pb.go @@ -28,7 +28,7 @@ type Product struct { unknownFields protoimpl.UnknownFields ProductId string `protobuf:"bytes,1,opt,name=Id,proto3" json:"Id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` + Name string `protobuf:"bytes,2,opt,name=ShortTypeName,proto3" json:"ShortTypeName,omitempty"` Description string `protobuf:"bytes,3,opt,name=Description,proto3" json:"Description,omitempty"` Price float64 `protobuf:"fixed64,4,opt,name=Price,proto3" json:"Price,omitempty"` CreatedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=CreatedAt,proto3" json:"CreatedAt,omitempty"` @@ -114,7 +114,7 @@ type CreateProductReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` + Name string `protobuf:"bytes,1,opt,name=ShortTypeName,proto3" json:"ShortTypeName,omitempty"` Description string `protobuf:"bytes,2,opt,name=Description,proto3" json:"Description,omitempty"` Price float64 `protobuf:"fixed64,3,opt,name=Price,proto3" json:"Price,omitempty"` } @@ -225,7 +225,7 @@ type UpdateProductReq struct { unknownFields protoimpl.UnknownFields ProductId string `protobuf:"bytes,1,opt,name=Id,proto3" json:"Id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` + Name string `protobuf:"bytes,2,opt,name=ShortTypeName,proto3" json:"ShortTypeName,omitempty"` Description string `protobuf:"bytes,3,opt,name=Description,proto3" json:"Description,omitempty"` Price float64 `protobuf:"fixed64,4,opt,name=Price,proto3" json:"Price,omitempty"` } @@ -519,6 +519,7 @@ var ( (*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp } ) + var file_catalog_write_service_products_proto_depIdxs = []int32{ 7, // 0: products_service.Product.CreatedAt:type_name -> google.protobuf.Timestamp 7, // 1: products_service.Product.UpdatedAt:type_name -> google.protobuf.Timestamp diff --git a/internal/services/catalogwriteservice/test/integration/products/data/repositories/pg_product_repository_integration_test.go b/internal/services/catalogwriteservice/test/integration/products/data/repositories/pg_product_repository_integration_test.go index 58d5fc0e..332b09c2 100644 --- a/internal/services/catalogwriteservice/test/integration/products/data/repositories/pg_product_repository_integration_test.go +++ b/internal/services/catalogwriteservice/test/integration/products/data/repositories/pg_product_repository_integration_test.go @@ -125,7 +125,7 @@ var _ = Describe("Product Repository Suite", func() { When("UpdateProduct function of ProductRepository executed", func() { BeforeEach(func() { // Update the name of the existing product - existingProduct.Name = "Updated Product Name" + existingProduct.Name = "Updated Product ShortTypeName" _, err = integrationFixture.ProductRepository.UpdateProduct(ctx, existingProduct) }) @@ -141,7 +141,7 @@ var _ = Describe("Product Repository Suite", func() { ) Expect(err).To(BeNil()) Expect(updatedProduct).NotTo(BeNil()) - Expect(updatedProduct.Name).To(Equal("Updated Product Name")) + Expect(updatedProduct.Name).To(Equal("Updated Product ShortTypeName")) // You can add more assertions to validate other properties of the updated product }) }) diff --git a/internal/services/catalogwriteservice/test/integration/products/features/updatingproduct/v1/update_product_test.go b/internal/services/catalogwriteservice/test/integration/products/features/updatingproduct/v1/update_product_test.go index 9dcc1c0a..e2b74baf 100644 --- a/internal/services/catalogwriteservice/test/integration/products/features/updatingproduct/v1/update_product_test.go +++ b/internal/services/catalogwriteservice/test/integration/products/features/updatingproduct/v1/update_product_test.go @@ -81,7 +81,7 @@ var _ = Describe("Update Product Feature", func() { BeforeEach(func() { command, err = v1.NewUpdateProduct( existingProduct.Id, - "Updated Product Name", + "Updated Product ShortTypeName", existingProduct.Description, existingProduct.Price, ) @@ -139,7 +139,7 @@ var _ = Describe("Update Product Feature", func() { id = uuid.NewV4() command, err = v1.NewUpdateProduct( id, - "Updated Product Name", + "Updated Product ShortTypeName", "Updated Product Description", 100, ) @@ -193,7 +193,7 @@ var _ = Describe("Update Product Feature", func() { BeforeEach(func() { command, err = v1.NewUpdateProduct( existingProduct.Id, - "Updated Product Name", + "Updated Product ShortTypeName", existingProduct.Description, existingProduct.Price, ) diff --git a/internal/services/catalogwriteservice/test/unit/products/features/creatingproduct/v1/create_product_unit_test.go b/internal/services/catalogwriteservice/test/unit/products/features/creatingproduct/v1/create_product_unit_test.go index 08170be0..5c591486 100644 --- a/internal/services/catalogwriteservice/test/unit/products/features/creatingproduct/v1/create_product_unit_test.go +++ b/internal/services/catalogwriteservice/test/unit/products/features/creatingproduct/v1/create_product_unit_test.go @@ -4,8 +4,10 @@ package v1 import ( + "fmt" "testing" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/core/cqrs" createProductCommand "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1" "github.com/mehdihadeli/go-ecommerce-microservices/internal/services/catalogwriteservice/internal/shared/testfixtures/unittest" @@ -31,21 +33,26 @@ func (c *createProductUnitTests) Test_New_Create_Product_Should_Return_No_Error_ description := gofakeit.EmojiDescription() price := gofakeit.Price(150, 6000) - updateProduct, err := createProductCommand.NewCreateProduct( + createProduct, err := createProductCommand.NewCreateProductWithValidation( name, description, price, ) + var g interface{} = createProduct + d, ok := g.(cqrs.Command) + if ok { + fmt.Println(d) + } - c.Assert().NotNil(updateProduct) - c.Assert().Equal(name, updateProduct.Name) - c.Assert().Equal(price, updateProduct.Price) + c.Assert().NotNil(createProduct) + c.Assert().Equal(name, createProduct.Name) + c.Assert().Equal(price, createProduct.Price) c.Require().NoError(err) } func (c *createProductUnitTests) Test_New_Create_Product_Should_Return_Error_For_Invalid_Price() { - command, err := createProductCommand.NewCreateProduct( + command, err := createProductCommand.NewCreateProductWithValidation( gofakeit.Name(), gofakeit.EmojiDescription(), 0, @@ -56,7 +63,7 @@ func (c *createProductUnitTests) Test_New_Create_Product_Should_Return_Error_For } func (c *createProductUnitTests) Test_New_Create_Product_Should_Return_Error_For_Empty_Name() { - command, err := createProductCommand.NewCreateProduct( + command, err := createProductCommand.NewCreateProductWithValidation( "", gofakeit.EmojiDescription(), 120, @@ -67,7 +74,7 @@ func (c *createProductUnitTests) Test_New_Create_Product_Should_Return_Error_For } func (c *createProductUnitTests) Test_New_Create_Product_Should_Return_Error_For_Empty_Description() { - command, err := createProductCommand.NewCreateProduct( + command, err := createProductCommand.NewCreateProductWithValidation( gofakeit.Name(), "", 120, diff --git a/internal/services/orderservice/test/end_to_end/orders/grpc/order_grpc_service_server_test.go b/internal/services/orderservice/test/end_to_end/orders/grpc/order_grpc_service_server_test.go index 3ba8e917..6b0c752a 100644 --- a/internal/services/orderservice/test/end_to_end/orders/grpc/order_grpc_service_server_test.go +++ b/internal/services/orderservice/test/end_to_end/orders/grpc/order_grpc_service_server_test.go @@ -62,7 +62,7 @@ package grpc // Quantity: uint64(gofakeit.Number(1, 10)), // Description: gofakeit.AdjectiveDescriptive(), // Price: gofakeit.Price(100, 10000), -// Title: gofakeit.Name(), +// Title: gofakeit.ShortTypeName(), // }, // }, // } From 31a10a56af57e3d00db321d1f82ebcc6cbd4fc25 Mon Sep 17 00:00:00 2001 From: Mehdi Hadeli Date: Fri, 19 Jan 2024 20:42:31 +0330 Subject: [PATCH 15/15] refactor: :recycle: cqrs refactoring --- internal/pkg/core/cqrs/command.go | 7 +++- internal/pkg/core/cqrs/command_test.go | 18 +++++++-- internal/pkg/core/cqrs/notification.go | 30 ++++++++++++++ internal/pkg/core/cqrs/query.go | 10 ++++- internal/pkg/core/cqrs/query_test.go | 40 +++++++++++-------- internal/pkg/core/cqrs/request.go | 22 ++++++++++ internal/pkg/core/cqrs/tx_request.go | 7 +++- .../mediator_transaction_pipeline.go | 4 +- .../creatingproduct/v1/create_product.go | 2 +- .../deletingproduct/v1/delete_product.go | 2 +- .../v1/delete_product_handler.go | 2 +- .../updatingproduct/v1/update_product.go | 2 +- .../v1/update_product_handler.go | 2 +- 13 files changed, 115 insertions(+), 33 deletions(-) create mode 100644 internal/pkg/core/cqrs/notification.go create mode 100644 internal/pkg/core/cqrs/request.go diff --git a/internal/pkg/core/cqrs/command.go b/internal/pkg/core/cqrs/command.go index a7509554..cbb90905 100644 --- a/internal/pkg/core/cqrs/command.go +++ b/internal/pkg/core/cqrs/command.go @@ -2,16 +2,21 @@ package cqrs type command struct { TypeInfo + Request } type Command interface { isCommand() + Request TypeInfo } func NewCommandByT[T any]() Command { - c := &command{TypeInfo: NewTypeInfoT[T]()} + c := &command{ + TypeInfo: NewTypeInfoT[T](), + Request: NewRequest(), + } return c } diff --git a/internal/pkg/core/cqrs/command_test.go b/internal/pkg/core/cqrs/command_test.go index 30897b8d..32cb7cf7 100644 --- a/internal/pkg/core/cqrs/command_test.go +++ b/internal/pkg/core/cqrs/command_test.go @@ -25,10 +25,20 @@ func Test_Command(t *testing.T) { assert.True(t, isImplementedCommand) var i interface{} = command - _, ok := i.(Command) - _, ok2 := i.(TypeInfo) - assert.True(t, ok) - assert.True(t, ok2) + _, isCommand := i.(Command) + _, isTypeInfo := i.(TypeInfo) + _, isQuery := i.(Query) + _, isRequest := i.(Request) + + assert.True(t, isCommand) + assert.True(t, isTypeInfo) + assert.True(t, isRequest) + assert.False(t, isQuery) + + assert.True(t, IsCommand(command)) + assert.True(t, IsRequest(command)) + assert.False(t, IsQuery(command)) + assert.Equal(t, command.ShortTypeName(), "*CreateProductTest") assert.Equal(t, command.FullTypeName(), "*cqrs.CreateProductTest") } diff --git a/internal/pkg/core/cqrs/notification.go b/internal/pkg/core/cqrs/notification.go new file mode 100644 index 00000000..974c03fa --- /dev/null +++ b/internal/pkg/core/cqrs/notification.go @@ -0,0 +1,30 @@ +package cqrs + +type notification struct { + TypeInfo +} + +type Notification interface { + isNotification() + + TypeInfo +} + +func NewNotificationByT[T any]() Notification { + n := ¬ification{ + TypeInfo: NewTypeInfoT[T](), + } + + return n +} + +func (c *notification) isNotification() { +} + +func IsNotification(obj interface{}) bool { + if _, ok := obj.(Notification); ok { + return true + } + + return false +} diff --git a/internal/pkg/core/cqrs/query.go b/internal/pkg/core/cqrs/query.go index e34d33dc..7957d848 100644 --- a/internal/pkg/core/cqrs/query.go +++ b/internal/pkg/core/cqrs/query.go @@ -2,15 +2,21 @@ package cqrs type query struct { TypeInfo + Request } type Query interface { - TypeInfo isQuery() + + Request + TypeInfo } func NewQueryByT[T any]() Query { - return &query{TypeInfo: NewTypeInfoT[T]()} + return &query{ + TypeInfo: NewTypeInfoT[T](), + Request: NewRequest(), + } } func (q *query) isQuery() { diff --git a/internal/pkg/core/cqrs/query_test.go b/internal/pkg/core/cqrs/query_test.go index d37e30c3..63120450 100644 --- a/internal/pkg/core/cqrs/query_test.go +++ b/internal/pkg/core/cqrs/query_test.go @@ -3,36 +3,42 @@ package cqrs import ( "testing" + "github.com/mehdihadeli/go-ecommerce-microservices/internal/pkg/reflection/typemapper" + uuid "github.com/satori/go.uuid" "github.com/stretchr/testify/assert" ) func Test_Query(t *testing.T) { query := &GetProductById{ - Query: NewQueryByT[GetProductById](), + Query: NewQueryByT[*GetProductById](), ProductID: uuid.NewV4(), } + isImplementedQuery := typemapper.ImplementedInterfaceT[Query](query) + assert.True(t, isImplementedQuery) + + var i interface{} = query + _, isQuery := i.(Query) + _, isTypeInfo := i.(TypeInfo) + _, isCommand := i.(Command) + _, isRequest := i.(Request) + + assert.True(t, isQuery) + assert.False(t, isCommand) + assert.True(t, isTypeInfo) + assert.True(t, isRequest) + assert.True(t, IsQuery(query)) -} + assert.False(t, IsCommand(query)) + assert.True(t, IsRequest(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) -//} + assert.Equal(t, query.ShortTypeName(), "*GetProductById") + assert.Equal(t, query.FullTypeName(), "*cqrs.GetProductById") +} type GetProductById struct { Query + ProductID uuid.UUID } diff --git a/internal/pkg/core/cqrs/request.go b/internal/pkg/core/cqrs/request.go new file mode 100644 index 00000000..bed4bdc5 --- /dev/null +++ b/internal/pkg/core/cqrs/request.go @@ -0,0 +1,22 @@ +package cqrs + +type request struct{} + +type Request interface { + isRequest() +} + +func NewRequest() Request { + return &request{} +} + +func (r *request) isRequest() { +} + +func IsRequest(obj interface{}) bool { + if _, ok := obj.(Request); ok { + return true + } + + return false +} diff --git a/internal/pkg/core/cqrs/tx_request.go b/internal/pkg/core/cqrs/tx_request.go index 86f880bb..68622321 100644 --- a/internal/pkg/core/cqrs/tx_request.go +++ b/internal/pkg/core/cqrs/tx_request.go @@ -1,6 +1,9 @@ package cqrs // https://www.mohitkhare.com/blog/go-naming-conventions/ -type ITxRequest interface { - IsTxRequest() bool + +type TxRequest interface { + Request + + isTxRequest() bool } diff --git a/internal/pkg/postgresgorm/pipelines/mediator_transaction_pipeline.go b/internal/pkg/postgresgorm/pipelines/mediator_transaction_pipeline.go index d8eb5863..3f360c05 100644 --- a/internal/pkg/postgresgorm/pipelines/mediator_transaction_pipeline.go +++ b/internal/pkg/postgresgorm/pipelines/mediator_transaction_pipeline.go @@ -34,8 +34,8 @@ func (m *mediatorTransactionPipeline) Handle( ) (interface{}, error) { requestName := typeMapper.GetSnakeTypeName(request) - txRequest, ok := request.(cqrs.ITxRequest) - if !ok || !txRequest.IsTxRequest() { + txRequest, ok := request.(cqrs.TxRequest) + if !ok || !txRequest.isTxRequest() { return next(ctx) } diff --git a/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product.go b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product.go index f5d977ae..72258679 100644 --- a/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product.go +++ b/internal/services/catalogwriteservice/internal/products/features/creatingproduct/v1/create_product.go @@ -52,7 +52,7 @@ func NewCreateProductWithValidation( return command, err } -func (c *CreateProduct) IsTxRequest() bool { +func (c *CreateProduct) isTxRequest() bool { return true } diff --git a/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product.go b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product.go index 5debf93b..d560852d 100644 --- a/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product.go +++ b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product.go @@ -28,7 +28,7 @@ func NewDeleteProductWithValidation(productID uuid.UUID) (*DeleteProduct, error) } // IsTxRequest for enabling transactions on the mediatr pipeline -func (c *DeleteProduct) IsTxRequest() bool { +func (c *DeleteProduct) isTxRequest() bool { return true } diff --git a/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_handler.go b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_handler.go index 840ab444..84b85cb9 100644 --- a/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_handler.go +++ b/internal/services/catalogwriteservice/internal/products/features/deletingproduct/v1/delete_product_handler.go @@ -34,7 +34,7 @@ func (c *deleteProductHandler) RegisterHandler() error { } // IsTxRequest for enabling transactions on the mediatr pipeline -func (c *deleteProductHandler) IsTxRequest() bool { +func (c *deleteProductHandler) isTxRequest() bool { return true } diff --git a/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product.go b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product.go index fc021d3b..256e3d66 100644 --- a/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product.go +++ b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product.go @@ -47,7 +47,7 @@ func NewUpdateProductWithValidation( } // IsTxRequest for enabling transactions on the mediatr pipeline -func (c *UpdateProduct) IsTxRequest() bool { +func (c *UpdateProduct) isTxRequest() bool { return true } diff --git a/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_handler.go b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_handler.go index 20ff42e7..cb592ebd 100644 --- a/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_handler.go +++ b/internal/services/catalogwriteservice/internal/products/features/updatingproduct/v1/update_product_handler.go @@ -39,7 +39,7 @@ func (c *updateProductHandler) RegisterHandler() error { } // IsTxRequest for enabling transactions on the mediatr pipeline -func (c *updateProductHandler) IsTxRequest() bool { +func (c *updateProductHandler) isTxRequest() bool { return true }