From 77ed9fcf85b96ba701f5ad70e7cda4571b226b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=B8=D1=82=D0=B0=20=D0=A8=D1=83=D0=B1?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Thu, 26 Jun 2025 12:08:46 +0000 Subject: [PATCH] [hw-4] add postgres db --- Makefile | 3 +- cart/Makefile | 1 + cart/go.mod | 49 +---- cart/go.sum | 141 +----------- .../domain/service/mock/repository_mock.go | 4 +- .../integration/cart_integration_test.go | 4 +- docker-compose.yaml | 36 +++ docs/README.md | 1 + docs/homework-3/loms.http | 36 +-- docs/homework-4/README.md | 33 +++ go.work.sum | 36 ++- loms/Makefile | 33 ++- loms/configs/values_local.yaml | 18 +- loms/db/migrations/00001_create_orders.sql | 20 ++ loms/db/migrations/00002_create_stocks.sql | 10 + loms/db/migrations/00003_add_stocks.sql | 24 ++ loms/go.mod | 74 ++++++- loms/go.sum | 207 ++++++++++++++++-- loms/internal/app/app.go | 48 +++- .../repository.go} | 0 .../domain/repository/orders/sqlc/db.go | 32 +++ .../domain/repository/orders/sqlc/models.go | 5 + .../domain/repository/orders/sqlc/querier.go | 18 ++ .../domain/repository/orders/sqlc/query.sql | 25 +++ .../repository/orders/sqlc/query.sql.go | 110 ++++++++++ .../repository/orders/sqlc/repository.go | 105 +++++++++ .../repository.go} | 0 .../stocks/{ => inmemory}/stock-data.json | 0 .../domain/repository/stocks/sqlc/db.go | 32 +++ .../domain/repository/stocks/sqlc/models.go | 11 + .../domain/repository/stocks/sqlc/querier.go | 18 ++ .../domain/repository/stocks/sqlc/query.sql | 24 ++ .../repository/stocks/sqlc/query.sql.go | 85 +++++++ .../repository/stocks/sqlc/repository.go | 137 ++++++++++++ .../service/mock/order_repository_mock.go | 4 +- .../service/mock/stock_repository_mock.go | 4 +- loms/internal/domain/service/service.go | 161 ++++++++------ loms/internal/domain/service/service_test.go | 61 +++++- loms/internal/infra/postgres/postgres.go | 56 +++++ loms/internal/infra/postgres/tx.go | 87 ++++++++ loms/internal/infra/tools/safecast.go | 19 ++ loms/sqlc.yaml | 28 +++ .../integration/loms_integration_test.go | 94 +++++++- make/bin-deps.mk | 31 +++ make/generate.mk | 13 +- make/lint.mk | 13 -- 46 files changed, 1582 insertions(+), 369 deletions(-) create mode 100644 docs/homework-4/README.md create mode 100644 loms/db/migrations/00001_create_orders.sql create mode 100644 loms/db/migrations/00002_create_stocks.sql create mode 100644 loms/db/migrations/00003_add_stocks.sql rename loms/internal/domain/repository/orders/{in_memory_repository.go => inmemory/repository.go} (100%) create mode 100644 loms/internal/domain/repository/orders/sqlc/db.go create mode 100644 loms/internal/domain/repository/orders/sqlc/models.go create mode 100644 loms/internal/domain/repository/orders/sqlc/querier.go create mode 100644 loms/internal/domain/repository/orders/sqlc/query.sql create mode 100644 loms/internal/domain/repository/orders/sqlc/query.sql.go create mode 100644 loms/internal/domain/repository/orders/sqlc/repository.go rename loms/internal/domain/repository/stocks/{in_memory_repository.go => inmemory/repository.go} (100%) rename loms/internal/domain/repository/stocks/{ => inmemory}/stock-data.json (100%) create mode 100644 loms/internal/domain/repository/stocks/sqlc/db.go create mode 100644 loms/internal/domain/repository/stocks/sqlc/models.go create mode 100644 loms/internal/domain/repository/stocks/sqlc/querier.go create mode 100644 loms/internal/domain/repository/stocks/sqlc/query.sql create mode 100644 loms/internal/domain/repository/stocks/sqlc/query.sql.go create mode 100644 loms/internal/domain/repository/stocks/sqlc/repository.go create mode 100644 loms/internal/infra/postgres/postgres.go create mode 100644 loms/internal/infra/postgres/tx.go create mode 100644 loms/internal/infra/tools/safecast.go create mode 100644 loms/sqlc.yaml create mode 100644 make/bin-deps.mk diff --git a/Makefile b/Makefile index eb6193d..3adf434 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ include make/lint.mk include make/build.mk include make/coverage.mk include make/generate.mk +include make/bin-deps.mk PKGS = $(shell go list ./... | grep -vE 'mock|config|generated|header|document|internal/pb') INTEGRATION_TAG = integration @@ -24,7 +25,7 @@ run-all: .PHONY: .integration-test integration-test: ALLURE_OUTPUT_PATH=$(shell pwd)/allure-results ALLURE_OUTPUT_FOLDER=cart go test -v -tags=$(INTEGRATION_TAG) ./cart/tests/integration - ALLURE_OUTPUT_PATH=$(shell pwd)/allure-results ALLURE_OUTPUT_FOLDER=loms go test -v -tags=$(INTEGRATION_TAG) ./loms/tests/integration + CGO_ENABLED=0 ALLURE_OUTPUT_PATH=$(shell pwd)/allure-results ALLURE_OUTPUT_FOLDER=loms go test -v -tags=$(INTEGRATION_TAG) ./loms/tests/integration bench: go test -bench=BenchmarkInMemoryRepository -benchmem ./cart/internal/domain/cart/repository -benchtime 3s diff --git a/cart/Makefile b/cart/Makefile index 0e71e38..275a030 100644 --- a/cart/Makefile +++ b/cart/Makefile @@ -8,6 +8,7 @@ bindir: build: bindir echo "build cart" + go build -o ${BINDIR}/cart cmd/server/main.go coverage: @go test -race -coverprofile=coverage.txt -covermode=atomic $(PKGS) diff --git a/cart/go.mod b/cart/go.mod index c1a72f3..9cb087e 100644 --- a/cart/go.mod +++ b/cart/go.mod @@ -10,58 +10,17 @@ require ( ) require ( - dario.cat/mergo v1.0.1 // indirect - github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/containerd/log v0.1.0 // indirect - github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v28.0.1+incompatible // indirect - github.com/docker/go-connections v0.5.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/ebitengine/purego v0.8.2 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect - github.com/go-logr/logr v1.4.2 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.2.6 // 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 - github.com/google/uuid v1.6.0 // indirect - github.com/klauspost/compress v1.17.4 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/leodido/go-urn v1.4.0 // indirect - github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect - github.com/magiconair/properties v1.8.10 // indirect - github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/patternmatcher v0.6.0 // indirect - github.com/moby/sys/sequential v0.5.0 // indirect - github.com/moby/sys/user v0.1.0 // indirect - github.com/moby/sys/userns v0.1.0 // indirect - github.com/moby/term v0.5.0 // indirect - github.com/morikuni/aec v1.0.0 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.1 // indirect - github.com/ozontech/allure-go/pkg/allure v0.6.14 // 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-20210106213030-5aafc221ea8c // indirect - github.com/shirou/gopsutil/v4 v4.25.1 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect - github.com/yusufpapurcu/wmi v1.2.4 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + github.com/rogpeppe/go-internal v1.13.1 // indirect go.opentelemetry.io/otel v1.36.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 // indirect - go.opentelemetry.io/otel/metric v1.36.0 // indirect go.opentelemetry.io/otel/sdk v1.36.0 // indirect - go.opentelemetry.io/otel/trace v1.36.0 // indirect - go.opentelemetry.io/proto/otlp v1.6.0 // indirect golang.org/x/crypto v0.37.0 // indirect golang.org/x/net v0.39.0 // indirect golang.org/x/text v0.24.0 // indirect @@ -74,7 +33,5 @@ require ( github.com/gojuno/minimock/v3 v3.4.5 github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect - github.com/ozontech/allure-go/pkg/framework v0.6.34 - github.com/testcontainers/testcontainers-go v0.37.0 golang.org/x/sys v0.33.0 // indirect ) diff --git a/cart/go.sum b/cart/go.sum index 86da82c..8f80db5 100644 --- a/cart/go.sum +++ b/cart/go.sum @@ -1,46 +1,13 @@ -dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= -dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -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-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -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/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= -github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= -github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= -github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= -github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= -github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v28.0.1+incompatible h1:FCHjSRdXhNRFjlHMTv4jUNlIBbTeRjrWfeFuJp7jpo0= -github.com/docker/docker v28.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= -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/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= -github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -50,101 +17,41 @@ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91 github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k= github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gojuno/minimock/v3 v3.4.5 h1:Jcb0tEYZvVlQNtAAYpg3jCOoSwss2c1/rNugYTzj304= github.com/gojuno/minimock/v3 v3.4.5/go.mod h1:o9F8i2IT8v3yirA7mmdpNGzh1WNesm6iQakMtQV6KiE= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= -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.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= -github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= -github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= -github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -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/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= -github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= -github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= -github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= -github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= -github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= -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/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -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.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= -github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= -github.com/ozontech/allure-go/pkg/allure v0.6.14 h1:lDamtSF+WtHQLg2+qQYijtC4Fk3KLGb6txNxxTZwUGc= -github.com/ozontech/allure-go/pkg/allure v0.6.14/go.mod h1:4oEG2yq+DGOzJS/ZjPc87C/mx3tAnlYpYonk77Ru/vQ= -github.com/ozontech/allure-go/pkg/framework v0.6.34 h1:IjM65Y3JP7ale7Ug3aBnFV4+c1NYYBCrgl/VrtEd/FY= -github.com/ozontech/allure-go/pkg/framework v0.6.34/go.mod h1:oISDLE6Tfww35TBQz+1nrtbLtyBqR6ELxOtJ+MVjHOw= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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 h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= -github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0ZqmLjXs= -github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/testcontainers/testcontainers-go v0.37.0 h1:L2Qc0vkTw2EHWQ08djon0D2uw7Z/PtHS/QzZZ5Ra/hg= -github.com/testcontainers/testcontainers-go v0.37.0/go.mod h1:QPzbxZhQ6Bclip9igjLFj6z0hs01bU8lrl2dHQmgFGM= -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/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= -github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= @@ -153,56 +60,17 @@ go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= -go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI= -go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= -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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/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/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= -golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 h1:0PeQib/pH3nB/5pEmFeVQJotzGohV0dq4Vcp09H5yhE= -google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34/go.mod h1:0awUlEkap+Pb1UMeJwJQQAdJQrt3moU7J2moTy69irI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM= @@ -212,8 +80,5 @@ google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= -gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/cart/internal/domain/service/mock/repository_mock.go b/cart/internal/domain/service/mock/repository_mock.go index 54ab2eb..674fa87 100644 --- a/cart/internal/domain/service/mock/repository_mock.go +++ b/cart/internal/domain/service/mock/repository_mock.go @@ -1,8 +1,8 @@ -// Code generated by http://github.com/gojuno/minimock (v3.4.5). DO NOT EDIT. +// Code generated by http://github.com/gojuno/minimock (v3.4.0). DO NOT EDIT. package mock -//go:generate minimock -i route256/cart/internal/domain/cart/service.Repository -o repository_mock.go -n RepositoryMock -p mock +//go:generate minimock -i route256/cart/internal/domain/service.Repository -o repository_mock.go -n RepositoryMock -p mock import ( "context" diff --git a/cart/tests/integration/cart_integration_test.go b/cart/tests/integration/cart_integration_test.go index df7ee57..9ff4117 100644 --- a/cart/tests/integration/cart_integration_test.go +++ b/cart/tests/integration/cart_integration_test.go @@ -19,9 +19,9 @@ import ( "github.com/testcontainers/testcontainers-go/wait" "google.golang.org/grpc" - lomsService "route256/cart/internal/adapter/client/loms" - productsService "route256/cart/internal/adapter/client/products" "route256/cart/internal/app" + lomsService "route256/cart/internal/clients/loms" + productsService "route256/cart/internal/clients/products" "route256/cart/internal/domain/entity" "route256/cart/internal/domain/model" "route256/cart/internal/domain/repository" diff --git a/docker-compose.yaml b/docker-compose.yaml index 539a8da..eca82af 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -17,7 +17,43 @@ services: build: context: . dockerfile: loms/Dockerfile + depends_on: + - postgres-master ports: - "8083:8083" - "8084:8084" - "8085:8085" + + postgres-master: + image: gitlab-registry.ozon.dev/go/classroom-18/students/base/postgres:16 + container_name: postgres-master + environment: + - POSTGRESQL_USERNAME=user + - POSTGRESQL_PASSWORD=password + - POSTGRESQL_DATABASE=route256 + - POSTGRESQL_REPLICATION_MODE=master + - POSTGRESQL_REPLICATION_USER=repl_user + - POSTGRESQL_REPLICATION_PASSWORD=repl_password + - POSTGRESQL_SYNCHRONOUS_COMMIT_MODE=on + - POSTGRESQL_NUM_SYNCHRONOUS_REPLICAS=1 + ports: + - "5433:5432" + + postgres-replica: + image: gitlab-registry.ozon.dev/go/classroom-18/students/base/postgres:16 + container_name: postgres-replica + depends_on: + - postgres-master + environment: + - POSTGRESQL_DATABASE=route256 + - POSTGRESQL_USERNAME=user + - POSTGRESQL_PASSWORD=password + - POSTGRESQL_REPLICATION_MODE=slave + - POSTGRESQL_REPLICATION_USER=repl_user + - POSTGRESQL_REPLICATION_PASSWORD=repl_password + - POSTGRESQL_MASTER_HOST=postgres-master + - POSTGRESQL_MASTER_PORT_NUMBER=5432 + - POSTGRESQL_SYNCHRONOUS_COMMIT_MODE=on + - POSTGRESQL_NUM_SYNCHRONOUS_REPLICAS=1 + ports: + - "5434:5432" diff --git a/docs/README.md b/docs/README.md index 4ab939b..a71e375 100644 --- a/docs/README.md +++ b/docs/README.md @@ -17,3 +17,4 @@ 1. [Основы Go](./homework-1) 2. [Тестирование в Go](./homework-2) 3. [Межсервисное взаимодействие и основы эксплуатации](./homework-3) +4. [Базы данных](./homework-4) diff --git a/docs/homework-3/loms.http b/docs/homework-3/loms.http index b346cac..fb52805 100644 --- a/docs/homework-3/loms.http +++ b/docs/homework-3/loms.http @@ -1,5 +1,5 @@ ### create normal order -POST http://localhost:8084/order/create +POST http://192.168.64.4:8084/order/create Content-Type: application/json { @@ -19,14 +19,14 @@ Content-Type: application/json ### get info, assert status="awaiting payment" -GET http://localhost:8084/order/info?orderId=1 +GET http://192.168.64.4:8084/order/info?orderId=1 Content-Type: application/json ### expected: 200 (OK) {"status":"awaiting payment","user":31337,"Items":[{"sku":1076963,"count":3},{"sku":135717466,"count":2}]} ### pay order -POST http://localhost:8084/order/pay +POST http://192.168.64.4:8084/order/pay Content-Type: application/json { @@ -36,14 +36,14 @@ Content-Type: application/json ### check actual status is "payed" -GET http://localhost:8084/order/info?orderId=1 +GET http://192.168.64.4:8084/order/info?orderId=1 Content-Type: application/json ### expected: 200 (OK) {"status":"payed","user":31337,"Items":[{"sku":1076963,"count":3},{"sku":135717466,"count":2}]} ### unable to cancel payed order -POST http://localhost:8084/order/cancel +POST http://192.168.64.4:8084/order/cancel Content-Type: application/json { @@ -53,14 +53,14 @@ Content-Type: application/json ### get unknown order -GET http://localhost:8084/order/info?orderId=404 +GET http://192.168.64.4:8084/order/info?orderId=404 Content-Type: application/json ### expected: 404 (Not Found) {"code": 5, ... } ### cancel order not exists -POST http://localhost:8084/order/cancel +POST http://192.168.64.4:8084/order/cancel Content-Type: application/json { @@ -70,7 +70,7 @@ Content-Type: application/json ### create order with item that has no stocks info -POST http://localhost:8084/order/create +POST http://192.168.64.4:8084/order/create Content-Type: application/json { @@ -86,13 +86,13 @@ Content-Type: application/json ### check order status is failed (not necessary, because no orderId after creation if any fails) -GET http://localhost:8084/order/info?orderId=2 +GET http://192.168.64.4:8084/order/info?orderId=2 Content-Type: application/json ### expected: 200 (OK) {"status":"failed","userId":31337,"Items":[{"sku":404,"count":3}]} ### cancel failed order -POST http://localhost:8084/order/cancel +POST http://192.168.64.4:8084/order/cancel Content-Type: application/json { @@ -102,21 +102,21 @@ Content-Type: application/json ### stock info for unknown sku -GET http://localhost:8084/stock/info?sku=404 +GET http://192.168.64.4:8084/stock/info?sku=404 Content-Type: application/json ### expected: 404 Not Found {"code":5, ... } ### stock info for normal sku -GET http://localhost:8084/stock/info?sku=135717466 +GET http://192.168.64.4:8084/stock/info?sku=135717466 Content-Type: application/json ### expected: 200 (OK) {"count":78} ### create order with count for sku more than stock -POST http://localhost:8084/order/create +POST http://192.168.64.4:8084/order/create Content-Type: application/json { @@ -131,13 +131,13 @@ Content-Type: application/json ### expected: 400 (Bad Request) {"code":9, ... } ### no change in stock info after failed order creation -GET http://localhost:8084/stock/info?sku=135717466 +GET http://192.168.64.4:8084/stock/info?sku=135717466 Content-Type: application/json ### expected: 200 (OK) {"count":78} ### create normal order for cancellation -POST http://localhost:8084/order/create +POST http://192.168.64.4:8084/order/create Content-Type: application/json { @@ -153,7 +153,7 @@ Content-Type: application/json ### cancel order -POST http://localhost:8084/order/cancel +POST http://192.168.64.4:8084/order/cancel Content-Type: application/json { @@ -163,14 +163,14 @@ Content-Type: application/json ### check canceled order status -GET http://localhost:8084/order/info?orderId=4 +GET http://192.168.64.4:8084/order/info?orderId=4 Content-Type: application/json ### expected: {"status":"cancelled","user":31337,"Items":[{"sku":1076963,"count":2}]} ### check stocks returns -GET http://localhost:8084/stock/info?sku=135717466 +GET http://192.168.64.4:8084/stock/info?sku=135717466 Content-Type: application/json ### expected: {"count":78}; 200 OK diff --git a/docs/homework-4/README.md b/docs/homework-4/README.md new file mode 100644 index 0000000..ff8d2d9 --- /dev/null +++ b/docs/homework-4/README.md @@ -0,0 +1,33 @@ +# Домашнее задание по модулю "Базы данных" + +Необходимо развернуть БД PostgreSQL для сервиса loms. Реализовать слой `Repository`, в котором будут походы в БД + +## Основное задание + +1. Для сервиса loms реализовать в слое `Repository` поход в БД +2. Развернуть экземпляр БД PostgreSQL в отдельном контейнере +3. Корректно использовать транзакции в операции создания заказа +4. Реализовать автоматические миграции, накатывающие схему БД и/или тестовые данные +5. SQL-код должен быть написан в виде raw. Без использования ORM или билдеров (можно sqlc) + +## Дополнительное задание + +1. Для БД поднять синхронную реплику. Балансировать read/write запросы между ними (write только в master, read в любую из реплик) +2. Написать по одному интеграционному тесту на каждый SQL-запрос в репозитории сервиса loms. Не забыть накатывать тестовые данные в миграции, после прогона тестов - удалить данные из БД +3. Реализовать SQL-запросы с помощью sqlc + +## Автоматические проверки + +Ваше решение должно проходить автоматические проверки: + +- Компиляция +- Линтер +- Unit-тесты +- Code coverage >40% +- Автотесты + +Прохождение автоматических проверок влияет на итоговую оценку за домашнюю работу. + +### Дедлайны сдачи и проверки задания: + +- 21 июня 23:59 (сдача) / 24 июня, 23:59 (проверка) diff --git a/go.work.sum b/go.work.sum index a68184e..8a818b2 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,32 +1,61 @@ cel.dev/expr v0.23.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/ClickHouse/ch-go v0.65.1/go.mod h1:bsodgURwmrkvkBe5jw1qnGDgyITsYErfONKAHn05nv4= +github.com/ClickHouse/clickhouse-go/v2 v2.34.0/go.mod h1:yioSINoRLVZkLyDzdMXPLRIqhDvel8iLBlwh6Iefso8= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0/go.mod h1:yAZHSGnqScoU556rBOVkwLze6WP5N+U11RHuWaGVxwY= +github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/coder/websocket v1.8.13/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= +github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= +github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/elastic/go-sysinfo v1.15.3/go.mod h1:K/cNrqYTDrSoMh2oDkYEMS2+a72GRxMvNP+GC+vRIlo= +github.com/elastic/go-windows v1.0.2/go.mod h1:bGcDpBzXgYSqM0Gx3DM4+UxFj300SZLixie9u9ixLM8= github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA= github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= +github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw= +github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7FPGZP2quo= github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= +github.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= +github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/hexdigest/gowrap v1.4.2/go.mod h1:s+1hE6qakgdaaLqgdwPAj5qKYVBCSbPJhEbx+I1ef/Q= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= github.com/lyft/protoc-gen-star/v2 v2.0.4-0.20230330145011-496ad1ac90a4/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= +github.com/mfridman/xflag v0.1.0/go.mod h1:/483ywM5ZO5SuMVjrIGquYNE5CzLrj5Ux/LxWWnjRaE= +github.com/microsoft/go-mssqldb v1.8.0/go.mod h1:6znkekS3T2vp0waiMhen4GPU1BiAsrP+iXHcE7a7rFo= +github.com/paulmach/orb v0.11.1/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= +github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= +github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/tursodatabase/libsql-client-go v0.0.0-20240902231107-85af5b9d094d/go.mod h1:l8xTsYB90uaVdMHXMCxKKLSgw5wLYBwBKKefNIUnm9s= +github.com/vertica/vertica-sql-go v1.3.3/go.mod h1:jnn2GFuv+O2Jcjktb7zyc4Utlbu9YVqpHH/lx63+1M4= +github.com/ydb-platform/ydb-go-genproto v0.0.0-20241112172322-ea1f63298f77/go.mod h1:Er+FePu1dNUieD+XTMDduGpQuCPssK5Q4BjF+IIXJ3I= +github.com/ydb-platform/ydb-go-sdk/v3 v3.108.1/go.mod h1:l5sSv153E18VvYcsmr51hok9Sjc16tEC8AXGbwrk+ho= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= +github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= go.opentelemetry.io/contrib/detectors/gcp v1.35.0/go.mod h1:qGWP8/+ILwMRIUf9uIVLloR1uo5ZYAslM4O6OqUi1DA= go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= @@ -40,9 +69,7 @@ golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= @@ -50,9 +77,12 @@ golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58 golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463/go.mod h1:U90ffi8eUL9MwPcrJylN5+Mk2v3vuPDptd5yyNUiRR8= +google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw= google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/grpc/examples v0.0.0-20230224211313-3775f633ce20/go.mod h1:Nr5H8+MlGWr5+xX/STzdoEqJrO+YteqFbMyCsrb6mH0= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= diff --git a/loms/Makefile b/loms/Makefile index 933c364..ca66db0 100644 --- a/loms/Makefile +++ b/loms/Makefile @@ -1,11 +1,40 @@ -BINDIR=${CURDIR}/bin +BINDIR=${CURDIR}/../bin PACKAGE=route256/loms +MIGRATIONS_FOLDER := ./db/migrations/ +LOCAL_DB_NAME := route256 +LOCAL_DB_DSN := postgresql://user:password@192.168.64.4:5433/route256?sslmode=disable + +PROD_USER := loms-user +PROD_PASS := loms-password +PROD_DB := postgres-master + +PROD_MIGRATIONS := ./loms/db/migrations/ bindir: mkdir -p ${BINDIR} build: bindir echo "build loms" + go build -o ${BINDIR}/loms cmd/server/main.go +# Used for CI run-migrations: - echo "run migrations" + $(GOOSE) -dir $(PROD_MIGRATIONS) postgres "postgresql://$(PROD_USER):$(PROD_PASS)@$(PROD_DB):5432/loms_db?sslmode=disable" up + +db-create-migration: + $(BINDIR)/goose -dir $(MIGRATIONS_FOLDER) create -s $(n) sql + +db-migrate: + $(BINDIR)/goose -dir $(MIGRATIONS_FOLDER) postgres "$(LOCAL_DB_DSN)" up + +db-migrate-down: + $(BINDIR)/goose -dir $(MIGRATIONS_FOLDER) postgres "$(LOCAL_DB_DSN)" down + +db-reset-local: + psql -c "drop database if exists \"$(LOCAL_DB_NAME)\"" + psql -c "create database \"$(LOCAL_DB_NAME)\"" + make db-migrate + +.PHONY: generate-sqlc +generate-sqlc: + $(BINDIR)/sqlc generate diff --git a/loms/configs/values_local.yaml b/loms/configs/values_local.yaml index ab407c8..f8781db 100644 --- a/loms/configs/values_local.yaml +++ b/loms/configs/values_local.yaml @@ -9,18 +9,18 @@ jaeger: port: 6831 db_master: - host: localhost + host: postgres-master port: 5432 - user: loms-user - password: loms-password - db_name: loms_db + user: user + password: password + db_name: route256 db_replica: - host: localhost - port: 5433 - user: loms-user - password: loms-password - db_name: loms_db + host: postgres-replica + port: 5432 + user: user + password: password + db_name: route256 kafka: host: localhost diff --git a/loms/db/migrations/00001_create_orders.sql b/loms/db/migrations/00001_create_orders.sql new file mode 100644 index 0000000..3ed43f1 --- /dev/null +++ b/loms/db/migrations/00001_create_orders.sql @@ -0,0 +1,20 @@ +-- +goose Up +CREATE TABLE + orders ( + id bigserial PRIMARY KEY, + status_name TEXT NOT NULL DEFAULT '', + user_id BIGINT NOT NULL + ); + +CREATE TABLE + order_items ( + id bigserial PRIMARY KEY, + order_id BIGINT NOT NULL REFERENCES orders (id) ON DELETE CASCADE, + sku BIGINT NOT NULL, + COUNT BIGINT NOT NULL CHECK (COUNT > 0) + ); + +-- +goose Down +DROP TABLE order_items; + +DROP TABLE orders; \ No newline at end of file diff --git a/loms/db/migrations/00002_create_stocks.sql b/loms/db/migrations/00002_create_stocks.sql new file mode 100644 index 0000000..70d3a26 --- /dev/null +++ b/loms/db/migrations/00002_create_stocks.sql @@ -0,0 +1,10 @@ +-- +goose Up +CREATE TABLE + stocks ( + sku BIGINT PRIMARY KEY, + total_count BIGINT NOT NULL, + reserved BIGINT NOT NULL DEFAULT 0 + ); + +-- +goose Down +DROP TABLE stocks; \ No newline at end of file diff --git a/loms/db/migrations/00003_add_stocks.sql b/loms/db/migrations/00003_add_stocks.sql new file mode 100644 index 0000000..c7a5591 --- /dev/null +++ b/loms/db/migrations/00003_add_stocks.sql @@ -0,0 +1,24 @@ +-- +goose Up +INSERT INTO + stocks (sku, total_count, reserved) +VALUES + (139275865, 65534, 0), + (2956315, 100, 30), + (1076963, 100, 35), + (135717466, 100, 20), + (135937324, 100, 30), + (1625903, 10000, 0), + (1148162, 100, 0); + +-- +goose Down +DELETE FROM stocks +WHERE + sku IN ( + 139275865, + 2956315, + 1076963, + 135717466, + 135937324, + 1625903, + 1148162 + ); \ No newline at end of file diff --git a/loms/go.mod b/loms/go.mod index 768013b..e3d56df 100644 --- a/loms/go.mod +++ b/loms/go.mod @@ -1,27 +1,87 @@ module route256/loms -go 1.23.1 +go 1.23.9 require ( github.com/gojuno/minimock/v3 v3.4.5 github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 + github.com/jackc/pgx/v5 v5.7.5 + github.com/opentracing/opentracing-go v1.2.0 + github.com/ozontech/allure-go/pkg/framework v0.6.34 github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.34.0 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.10.0 + github.com/testcontainers/testcontainers-go v0.37.0 google.golang.org/grpc v1.73.0 google.golang.org/protobuf v1.36.6 gopkg.in/yaml.v3 v3.0.1 ) +require ( + dario.cat/mergo v1.0.1 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/docker v28.0.1+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/ebitengine/purego v0.8.4 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.10 // indirect + github.com/mfridman/interpolate v0.0.2 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/sys/userns v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/sethvargo/go-retry v0.3.0 // indirect + github.com/shirou/gopsutil/v4 v4.25.1 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 // indirect + go.opentelemetry.io/otel/metric v1.36.0 // indirect + go.opentelemetry.io/otel/sdk v1.36.0 // indirect + go.opentelemetry.io/otel/trace v1.36.0 // indirect + go.opentelemetry.io/proto/otlp v1.7.0 // indirect + go.uber.org/multierr v1.11.0 // indirect +) + require ( github.com/davecgh/go-spew v1.1.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/ozontech/allure-go/pkg/allure v0.6.14 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.14.1 // indirect - golang.org/x/net v0.38.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/text v0.23.0 // indirect + github.com/pressly/goose/v3 v3.24.3 + golang.org/x/crypto v0.38.0 // indirect + golang.org/x/net v0.40.0 // indirect + golang.org/x/sync v0.14.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/text v0.25.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect ) diff --git a/loms/go.sum b/loms/go.sum index cdbb7ed..4025fdb 100644 --- a/loms/go.sum +++ b/loms/go.sum @@ -1,62 +1,224 @@ +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +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-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +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/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v28.0.1+incompatible h1:FCHjSRdXhNRFjlHMTv4jUNlIBbTeRjrWfeFuJp7jpo0= +github.com/docker/docker v28.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +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/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/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= +github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gojuno/minimock/v3 v3.4.5 h1:Jcb0tEYZvVlQNtAAYpg3jCOoSwss2c1/rNugYTzj304= github.com/gojuno/minimock/v3 v3.4.5/go.mod h1:o9F8i2IT8v3yirA7mmdpNGzh1WNesm6iQakMtQV6KiE= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs= +github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +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.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY= +github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +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/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= +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/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= +github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +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.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/ozontech/allure-go/pkg/allure v0.6.14 h1:lDamtSF+WtHQLg2+qQYijtC4Fk3KLGb6txNxxTZwUGc= +github.com/ozontech/allure-go/pkg/allure v0.6.14/go.mod h1:4oEG2yq+DGOzJS/ZjPc87C/mx3tAnlYpYonk77Ru/vQ= +github.com/ozontech/allure-go/pkg/framework v0.6.34 h1:IjM65Y3JP7ale7Ug3aBnFV4+c1NYYBCrgl/VrtEd/FY= +github.com/ozontech/allure-go/pkg/framework v0.6.34/go.mod h1:oISDLE6Tfww35TBQz+1nrtbLtyBqR6ELxOtJ+MVjHOw= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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 h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/pressly/goose/v3 v3.24.3 h1:DSWWNwwggVUsYZ0X2VitiAa9sKuqtBfe+Jr9zFGwWlM= +github.com/pressly/goose/v3 v3.24.3/go.mod h1:v9zYL4xdViLHCUUJh/mhjnm6JrK7Eul8AS93IxiZM4E= +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/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE= +github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas= +github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0ZqmLjXs= +github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/testcontainers/testcontainers-go v0.37.0 h1:L2Qc0vkTw2EHWQ08djon0D2uw7Z/PtHS/QzZZ5Ra/hg= +github.com/testcontainers/testcontainers-go v0.37.0/go.mod h1:QPzbxZhQ6Bclip9igjLFj6z0hs01bU8lrl2dHQmgFGM= +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/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= -go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= +go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os= +go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= +golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI= +golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ= +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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/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.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/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/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= @@ -68,5 +230,16 @@ google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +modernc.org/libc v1.65.0 h1:e183gLDnAp9VJh6gWKdTy0CThL9Pt7MfcR/0bgb7Y1Y= +modernc.org/libc v1.65.0/go.mod h1:7m9VzGq7APssBTydds2zBcxGREwvIGpuUBaKTXdm2Qs= +modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= +modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= +modernc.org/memory v1.10.0 h1:fzumd51yQ1DxcOxSO+S6X7+QTuVU+n8/Aj7swYjFfC4= +modernc.org/memory v1.10.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= +modernc.org/sqlite v1.37.0 h1:s1TMe7T3Q3ovQiK2Ouz4Jwh7dw4ZDqbebSDTlSJdfjI= +modernc.org/sqlite v1.37.0/go.mod h1:5YiWv+YviqGMuGw4V+PNplcyaJ5v+vQd7TQOgkACoJM= diff --git a/loms/internal/app/app.go b/loms/internal/app/app.go index d5cc011..cb0a2d0 100644 --- a/loms/internal/app/app.go +++ b/loms/internal/app/app.go @@ -9,6 +9,7 @@ import ( "time" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/jackc/pgx/v5/pgxpool" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "google.golang.org/grpc" @@ -16,11 +17,12 @@ import ( "google.golang.org/grpc/reflection" "route256/loms/internal/app/server" - ordersRepository "route256/loms/internal/domain/repository/orders" - stocksRepository "route256/loms/internal/domain/repository/stocks" + ordersRepository "route256/loms/internal/domain/repository/orders/sqlc" + stocksRepository "route256/loms/internal/domain/repository/stocks/sqlc" "route256/loms/internal/domain/service" "route256/loms/internal/infra/config" mw "route256/loms/internal/infra/grpc/middleware" + "route256/loms/internal/infra/postgres" pb "route256/pkg/api/loms/v1" ) @@ -50,13 +52,16 @@ func NewApp(configPath string) (*App, error) { log.WithLevel(zerolog.GlobalLevel()).Msgf("using logging level=`%s`", zerolog.GlobalLevel().String()) - stockRepo, err := stocksRepository.NewInMemoryRepository(100) + masterPool, replicaPool, err := getPostgresPools(c) if err != nil { - return nil, fmt.Errorf("stocksRepository.NewInMemoryRepository: %w", err) + return nil, err } - orderRepo := ordersRepository.NewInMemoryRepository(100) - service := service.NewLomsService(orderRepo, stockRepo) + stockRepo := stocksRepository.NewStockRepository(masterPool, replicaPool) + orderRepo := ordersRepository.NewOrderRepository(masterPool) + txManager := postgres.NewTxManager(masterPool, replicaPool) + + service := service.NewLomsService(orderRepo, stockRepo, txManager) controller := server.NewServer(service) app := &App{ @@ -117,3 +122,34 @@ func (app *App) ListenAndServe() error { return gwServer.ListenAndServe() } + +func getPostgresPools(c *config.Config) (masterPool, replicaPool *pgxpool.Pool, err error) { + masterConn := fmt.Sprintf( + "postgresql://%s:%s@%s:%s/%s?sslmode=disable", + c.DatabaseMaster.User, + c.DatabaseMaster.Password, + c.DatabaseMaster.Host, + c.DatabaseMaster.Port, + c.DatabaseMaster.DBName, + ) + + replicaConn := fmt.Sprintf( + "postgresql://%s:%s@%s:%s/%s?sslmode=disable", + c.DatabaseReplica.User, + c.DatabaseReplica.Password, + c.DatabaseReplica.Host, + c.DatabaseReplica.Port, + c.DatabaseReplica.DBName, + ) + + pools, err := postgres.NewPools(context.Background(), masterConn, replicaConn) + if err != nil { + return nil, nil, err + } + + if len(pools) != 2 { + return nil, nil, fmt.Errorf("got wrong number of pools when establishing postgres connection") + } + + return pools[0], pools[1], nil +} diff --git a/loms/internal/domain/repository/orders/in_memory_repository.go b/loms/internal/domain/repository/orders/inmemory/repository.go similarity index 100% rename from loms/internal/domain/repository/orders/in_memory_repository.go rename to loms/internal/domain/repository/orders/inmemory/repository.go diff --git a/loms/internal/domain/repository/orders/sqlc/db.go b/loms/internal/domain/repository/orders/sqlc/db.go new file mode 100644 index 0000000..2725108 --- /dev/null +++ b/loms/internal/domain/repository/orders/sqlc/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 + +package sqlc + +import ( + "context" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgconn" +) + +type DBTX interface { + Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) + Query(context.Context, string, ...interface{}) (pgx.Rows, error) + QueryRow(context.Context, string, ...interface{}) pgx.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx pgx.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/loms/internal/domain/repository/orders/sqlc/models.go b/loms/internal/domain/repository/orders/sqlc/models.go new file mode 100644 index 0000000..dca13da --- /dev/null +++ b/loms/internal/domain/repository/orders/sqlc/models.go @@ -0,0 +1,5 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 + +package sqlc diff --git a/loms/internal/domain/repository/orders/sqlc/querier.go b/loms/internal/domain/repository/orders/sqlc/querier.go new file mode 100644 index 0000000..9b3e821 --- /dev/null +++ b/loms/internal/domain/repository/orders/sqlc/querier.go @@ -0,0 +1,18 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 + +package sqlc + +import ( + "context" +) + +type Querier interface { + OrderAddItem(ctx context.Context, arg *OrderAddItemParams) error + OrderCreate(ctx context.Context, arg *OrderCreateParams) (int64, error) + OrderGetByID(ctx context.Context, id int64) ([]*OrderGetByIDRow, error) + OrderSetStatus(ctx context.Context, arg *OrderSetStatusParams) (int64, error) +} + +var _ Querier = (*Queries)(nil) diff --git a/loms/internal/domain/repository/orders/sqlc/query.sql b/loms/internal/domain/repository/orders/sqlc/query.sql new file mode 100644 index 0000000..c03ffe0 --- /dev/null +++ b/loms/internal/domain/repository/orders/sqlc/query.sql @@ -0,0 +1,25 @@ +-- name: OrderCreate :one +insert into orders (status_name, user_id) +values ($1, $2) +returning id; + +-- name: OrderAddItem :exec +insert into order_items (order_id, sku, count) +select $1, $2, $3; + +-- name: OrderSetStatus :execrows +update orders +set status_name = $2 +where id = $1; + +-- name: OrderGetByID :many +select + o.id as order_id, + o.status_name as status, + o.user_id, + oi.sku, + oi.count +from orders o +left join order_items oi on oi.order_id = o.id +where o.id = $1 +order by oi.id; \ No newline at end of file diff --git a/loms/internal/domain/repository/orders/sqlc/query.sql.go b/loms/internal/domain/repository/orders/sqlc/query.sql.go new file mode 100644 index 0000000..1e2c110 --- /dev/null +++ b/loms/internal/domain/repository/orders/sqlc/query.sql.go @@ -0,0 +1,110 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 +// source: query.sql + +package sqlc + +import ( + "context" +) + +const orderAddItem = `-- name: OrderAddItem :exec +insert into order_items (order_id, sku, count) +select $1, $2, $3 +` + +type OrderAddItemParams struct { + OrderID int64 + Sku int64 + Count int64 +} + +func (q *Queries) OrderAddItem(ctx context.Context, arg *OrderAddItemParams) error { + _, err := q.db.Exec(ctx, orderAddItem, arg.OrderID, arg.Sku, arg.Count) + return err +} + +const orderCreate = `-- name: OrderCreate :one +insert into orders (status_name, user_id) +values ($1, $2) +returning id +` + +type OrderCreateParams struct { + StatusName string + UserID int64 +} + +func (q *Queries) OrderCreate(ctx context.Context, arg *OrderCreateParams) (int64, error) { + row := q.db.QueryRow(ctx, orderCreate, arg.StatusName, arg.UserID) + var id int64 + err := row.Scan(&id) + return id, err +} + +const orderGetByID = `-- name: OrderGetByID :many +select + o.id as order_id, + o.status_name as status, + o.user_id, + oi.sku, + oi.count +from orders o +left join order_items oi on oi.order_id = o.id +where o.id = $1 +order by oi.id +` + +type OrderGetByIDRow struct { + OrderID int64 + Status string + UserID int64 + Sku *int64 + Count *int64 +} + +func (q *Queries) OrderGetByID(ctx context.Context, id int64) ([]*OrderGetByIDRow, error) { + rows, err := q.db.Query(ctx, orderGetByID, id) + if err != nil { + return nil, err + } + defer rows.Close() + var items []*OrderGetByIDRow + for rows.Next() { + var i OrderGetByIDRow + if err := rows.Scan( + &i.OrderID, + &i.Status, + &i.UserID, + &i.Sku, + &i.Count, + ); err != nil { + return nil, err + } + items = append(items, &i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const orderSetStatus = `-- name: OrderSetStatus :execrows +update orders +set status_name = $2 +where id = $1 +` + +type OrderSetStatusParams struct { + ID int64 + StatusName string +} + +func (q *Queries) OrderSetStatus(ctx context.Context, arg *OrderSetStatusParams) (int64, error) { + result, err := q.db.Exec(ctx, orderSetStatus, arg.ID, arg.StatusName) + if err != nil { + return 0, err + } + return result.RowsAffected(), nil +} diff --git a/loms/internal/domain/repository/orders/sqlc/repository.go b/loms/internal/domain/repository/orders/sqlc/repository.go new file mode 100644 index 0000000..fda855c --- /dev/null +++ b/loms/internal/domain/repository/orders/sqlc/repository.go @@ -0,0 +1,105 @@ +package sqlc + +import ( + "context" + "fmt" + + "github.com/jackc/pgx/v5/pgxpool" + + "route256/loms/internal/domain/entity" + "route256/loms/internal/domain/model" + "route256/loms/internal/domain/service" + "route256/loms/internal/infra/postgres" +) + +type orderRepo struct { + pool *pgxpool.Pool +} + +func NewOrderRepository(pool *pgxpool.Pool) service.OrderRepository { + return &orderRepo{ + pool: pool, + } +} + +func (o *orderRepo) GetQuerier(ctx context.Context) *Queries { + tx, ok := postgres.TxFromCtx(ctx) + if ok { + return New(tx) + } + + return New(o.pool) +} + +func (o *orderRepo) OrderCreate(ctx context.Context, order *entity.Order) (entity.ID, error) { + querier := o.GetQuerier(ctx) + + id, err := querier.OrderCreate(ctx, &OrderCreateParams{ + StatusName: order.Status, + UserID: int64(order.UserID), + }) + if err != nil { + return 0, fmt.Errorf("querier.OrderCreate: %w", err) + } + + for _, item := range order.Items { + if err := querier.OrderAddItem(ctx, &OrderAddItemParams{ + OrderID: id, + Sku: int64(item.ID), + Count: int64(item.Count), + }); err != nil { + return 0, fmt.Errorf("querier.OrderAddItem: %w", err) + } + } + + return entity.ID(id), nil +} + +func (o *orderRepo) OrderGetByID(ctx context.Context, orderID entity.ID) (*entity.Order, error) { + querier := o.GetQuerier(ctx) + + rows, err := querier.OrderGetByID(ctx, int64(orderID)) + if err != nil { + return nil, fmt.Errorf("querier.OrderGetByID: %w", err) + } + + if len(rows) == 0 { + return nil, model.ErrOrderNotFound + } + + items := make([]entity.OrderItem, len(rows)) + for i, row := range rows { + items[i] = entity.OrderItem{ + ID: entity.Sku(*row.Sku), + //nolint:gosec // will not overflow, uint32 is stored as int64 + Count: uint32(*row.Count), + } + } + + order := &entity.Order{ + OrderID: orderID, + Status: rows[0].Status, + UserID: entity.ID(rows[0].UserID), + Items: items, + } + + return order, nil +} + +func (o *orderRepo) OrderSetStatus(ctx context.Context, orderID entity.ID, newStatus string) error { + querier := o.GetQuerier(ctx) + + rows, err := querier.OrderSetStatus(ctx, &OrderSetStatusParams{ + ID: int64(orderID), + StatusName: newStatus, + }) + if err != nil { + return fmt.Errorf("querier.OrderSetStatus: %w", err) + } + + if rows == 0 { + return model.ErrOrderNotFound + } + + return nil +} diff --git a/loms/internal/domain/repository/stocks/in_memory_repository.go b/loms/internal/domain/repository/stocks/inmemory/repository.go similarity index 100% rename from loms/internal/domain/repository/stocks/in_memory_repository.go rename to loms/internal/domain/repository/stocks/inmemory/repository.go diff --git a/loms/internal/domain/repository/stocks/stock-data.json b/loms/internal/domain/repository/stocks/inmemory/stock-data.json similarity index 100% rename from loms/internal/domain/repository/stocks/stock-data.json rename to loms/internal/domain/repository/stocks/inmemory/stock-data.json diff --git a/loms/internal/domain/repository/stocks/sqlc/db.go b/loms/internal/domain/repository/stocks/sqlc/db.go new file mode 100644 index 0000000..2725108 --- /dev/null +++ b/loms/internal/domain/repository/stocks/sqlc/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 + +package sqlc + +import ( + "context" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgconn" +) + +type DBTX interface { + Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) + Query(context.Context, string, ...interface{}) (pgx.Rows, error) + QueryRow(context.Context, string, ...interface{}) pgx.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx pgx.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/loms/internal/domain/repository/stocks/sqlc/models.go b/loms/internal/domain/repository/stocks/sqlc/models.go new file mode 100644 index 0000000..75797d3 --- /dev/null +++ b/loms/internal/domain/repository/stocks/sqlc/models.go @@ -0,0 +1,11 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 + +package sqlc + +type Stock struct { + Sku int64 + TotalCount int64 + Reserved int64 +} diff --git a/loms/internal/domain/repository/stocks/sqlc/querier.go b/loms/internal/domain/repository/stocks/sqlc/querier.go new file mode 100644 index 0000000..ef38c84 --- /dev/null +++ b/loms/internal/domain/repository/stocks/sqlc/querier.go @@ -0,0 +1,18 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 + +package sqlc + +import ( + "context" +) + +type Querier interface { + StockCancel(ctx context.Context, arg *StockCancelParams) (int64, error) + StockGetByID(ctx context.Context, sku int64) (*Stock, error) + StockReserve(ctx context.Context, arg *StockReserveParams) (int64, error) + StockReserveRemove(ctx context.Context, arg *StockReserveRemoveParams) (int64, error) +} + +var _ Querier = (*Queries)(nil) diff --git a/loms/internal/domain/repository/stocks/sqlc/query.sql b/loms/internal/domain/repository/stocks/sqlc/query.sql new file mode 100644 index 0000000..a7c57d7 --- /dev/null +++ b/loms/internal/domain/repository/stocks/sqlc/query.sql @@ -0,0 +1,24 @@ +-- name: StockGetByID :one +select sku, total_count, reserved +from stocks +where sku = $1 +limit 1; + +-- name: StockReserve :execrows +update stocks +set reserved = reserved + $2 +where sku = $1 + and total_count >= reserved + $2; + +-- name: StockReserveRemove :execrows +update stocks +set reserved = reserved - $2, + total_count = total_count - $2 +where sku = $1 + and reserved >= $2 and total_count >= $2; + +-- name: StockCancel :execrows +update stocks +set reserved = reserved - $2 +where sku = $1 + and reserved >= $2; \ No newline at end of file diff --git a/loms/internal/domain/repository/stocks/sqlc/query.sql.go b/loms/internal/domain/repository/stocks/sqlc/query.sql.go new file mode 100644 index 0000000..6e55f6a --- /dev/null +++ b/loms/internal/domain/repository/stocks/sqlc/query.sql.go @@ -0,0 +1,85 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 +// source: query.sql + +package sqlc + +import ( + "context" +) + +const stockCancel = `-- name: StockCancel :execrows +update stocks +set reserved = reserved - $2 +where sku = $1 + and reserved >= $2 +` + +type StockCancelParams struct { + Sku int64 + Reserved int64 +} + +func (q *Queries) StockCancel(ctx context.Context, arg *StockCancelParams) (int64, error) { + result, err := q.db.Exec(ctx, stockCancel, arg.Sku, arg.Reserved) + if err != nil { + return 0, err + } + return result.RowsAffected(), nil +} + +const stockGetByID = `-- name: StockGetByID :one +select sku, total_count, reserved +from stocks +where sku = $1 +limit 1 +` + +func (q *Queries) StockGetByID(ctx context.Context, sku int64) (*Stock, error) { + row := q.db.QueryRow(ctx, stockGetByID, sku) + var i Stock + err := row.Scan(&i.Sku, &i.TotalCount, &i.Reserved) + return &i, err +} + +const stockReserve = `-- name: StockReserve :execrows +update stocks +set reserved = reserved + $2 +where sku = $1 + and total_count >= reserved + $2 +` + +type StockReserveParams struct { + Sku int64 + Reserved int64 +} + +func (q *Queries) StockReserve(ctx context.Context, arg *StockReserveParams) (int64, error) { + result, err := q.db.Exec(ctx, stockReserve, arg.Sku, arg.Reserved) + if err != nil { + return 0, err + } + return result.RowsAffected(), nil +} + +const stockReserveRemove = `-- name: StockReserveRemove :execrows +update stocks +set reserved = reserved - $2, + total_count = total_count - $2 +where sku = $1 + and reserved >= $2 and total_count >= $2 +` + +type StockReserveRemoveParams struct { + Sku int64 + Reserved int64 +} + +func (q *Queries) StockReserveRemove(ctx context.Context, arg *StockReserveRemoveParams) (int64, error) { + result, err := q.db.Exec(ctx, stockReserveRemove, arg.Sku, arg.Reserved) + if err != nil { + return 0, err + } + return result.RowsAffected(), nil +} diff --git a/loms/internal/domain/repository/stocks/sqlc/repository.go b/loms/internal/domain/repository/stocks/sqlc/repository.go new file mode 100644 index 0000000..a367042 --- /dev/null +++ b/loms/internal/domain/repository/stocks/sqlc/repository.go @@ -0,0 +1,137 @@ +package sqlc + +import ( + "context" + "errors" + "fmt" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgxpool" + + "route256/loms/internal/domain/entity" + "route256/loms/internal/domain/model" + "route256/loms/internal/domain/service" + "route256/loms/internal/infra/postgres" + "route256/loms/internal/infra/tools" +) + +type stockRepo struct { + read *pgxpool.Pool + write *pgxpool.Pool +} + +func NewStockRepository(write, read *pgxpool.Pool) service.StockRepository { + return &stockRepo{ + read: read, + write: write, + } +} + +func (s *stockRepo) GetQuerier(ctx context.Context) *Queries { + tx, ok := postgres.TxFromCtx(ctx) + if ok { + return New(tx) + } + + return New(s.write) +} + +func (s *stockRepo) StockReserve(ctx context.Context, stock *entity.Stock) error { + querier := s.GetQuerier(ctx) + + rows, err := querier.StockReserve(ctx, &StockReserveParams{ + Sku: int64(stock.Item.ID), + Reserved: int64(stock.Reserved), + }) + if err != nil { + return fmt.Errorf("querier.StockReserve: %w", err) + } + + if rows == 0 { + return model.ErrNotEnoughStocks + } + + return nil +} + +func (s *stockRepo) StockReserveRemove(ctx context.Context, stock *entity.Stock) error { + querier := s.GetQuerier(ctx) + + rows, err := querier.StockReserveRemove(ctx, &StockReserveRemoveParams{ + Sku: int64(stock.Item.ID), + Reserved: int64(stock.Reserved), + }) + if err != nil { + return fmt.Errorf("querier.StockReserveRemove: %w", err) + } + + if rows > 0 { + return nil + } + + _, err = querier.StockGetByID(ctx, int64(stock.Item.ID)) + switch { + case errors.Is(err, pgx.ErrNoRows): + return model.ErrUnknownStock + case err != nil: + return fmt.Errorf("querier.StockGetByID: %w", err) + default: + return model.ErrNotEnoughStocks + } +} + +func (s *stockRepo) StockCancel(ctx context.Context, stock *entity.Stock) error { + querier := s.GetQuerier(ctx) + + rows, err := querier.StockCancel(ctx, &StockCancelParams{ + Sku: int64(stock.Item.ID), + Reserved: int64(stock.Reserved), + }) + if err != nil { + return fmt.Errorf("querier.StockCancel: %w", err) + } + + if rows > 0 { + return nil + } + + _, err = querier.StockGetByID(ctx, int64(stock.Item.ID)) + switch { + case errors.Is(err, pgx.ErrNoRows): + return model.ErrUnknownStock + case err != nil: + return fmt.Errorf("querier.StockGetByID: %w", err) + default: + return model.ErrNotEnoughStocks + } +} + +func (s *stockRepo) StockGetByID(ctx context.Context, sku entity.Sku) (*entity.Stock, error) { + querier := s.GetQuerier(ctx) + + stock, err := querier.StockGetByID(ctx, int64(sku)) + switch { + case errors.Is(err, pgx.ErrNoRows): + return nil, model.ErrUnknownStock + case err != nil: + return nil, fmt.Errorf("querier.StockGetByID: %w", err) + default: + count, castErr := tools.SafeCastInt64ToUInt32(stock.TotalCount) + if castErr != nil { + return nil, castErr + } + + reserved, castErr := tools.SafeCastInt64ToUInt32(stock.Reserved) + if castErr != nil { + return nil, castErr + } + + return &entity.Stock{ + Item: entity.OrderItem{ + ID: entity.Sku(stock.Sku), + Count: count, + }, + Reserved: reserved, + }, nil + } +} diff --git a/loms/internal/domain/service/mock/order_repository_mock.go b/loms/internal/domain/service/mock/order_repository_mock.go index 8f1e2dc..4a77703 100644 --- a/loms/internal/domain/service/mock/order_repository_mock.go +++ b/loms/internal/domain/service/mock/order_repository_mock.go @@ -1,8 +1,8 @@ -// Code generated by http://github.com/gojuno/minimock (v3.4.5). DO NOT EDIT. +// Code generated by http://github.com/gojuno/minimock (v3.4.0). DO NOT EDIT. package mock -//go:generate minimock -i route256/loms/internal/domain/loms/service.OrderRepository -o order_repository_mock.go -n OrderRepositoryMock -p mock +//go:generate minimock -i route256/loms/internal/domain/service.OrderRepository -o order_repository_mock.go -n OrderRepositoryMock -p mock import ( "context" diff --git a/loms/internal/domain/service/mock/stock_repository_mock.go b/loms/internal/domain/service/mock/stock_repository_mock.go index 62f73b4..236bac0 100644 --- a/loms/internal/domain/service/mock/stock_repository_mock.go +++ b/loms/internal/domain/service/mock/stock_repository_mock.go @@ -1,8 +1,8 @@ -// Code generated by http://github.com/gojuno/minimock (v3.4.5). DO NOT EDIT. +// Code generated by http://github.com/gojuno/minimock (v3.4.0). DO NOT EDIT. package mock -//go:generate minimock -i route256/loms/internal/domain/loms/service.StockRepository -o stock_repository_mock.go -n StockRepositoryMock -p mock +//go:generate minimock -i route256/loms/internal/domain/service.StockRepository -o stock_repository_mock.go -n StockRepositoryMock -p mock import ( "context" diff --git a/loms/internal/domain/service/service.go b/loms/internal/domain/service/service.go index b579e69..663b87b 100644 --- a/loms/internal/domain/service/service.go +++ b/loms/internal/domain/service/service.go @@ -28,15 +28,24 @@ type StockRepository interface { StockGetByID(ctx context.Context, sku entity.Sku) (*entity.Stock, error) } -type LomsService struct { - orders OrderRepository - stocks StockRepository +type txManager interface { + WriteWithTransaction(ctx context.Context, fn func(ctx context.Context) error) (err error) + ReadWithTransaction(ctx context.Context, fn func(ctx context.Context) error) (err error) + WriteWithRepeatableRead(ctx context.Context, fn func(ctx context.Context) error) (err error) + ReadWithRepeatableRead(ctx context.Context, fn func(ctx context.Context) error) (err error) } -func NewLomsService(orderRepo OrderRepository, stockRepo StockRepository) *LomsService { +type LomsService struct { + orders OrderRepository + stocks StockRepository + txManager txManager +} + +func NewLomsService(orderRepo OrderRepository, stockRepo StockRepository, txManager txManager) *LomsService { return &LomsService{ - orders: orderRepo, - stocks: stockRepo, + orders: orderRepo, + stocks: stockRepo, + txManager: txManager, } } @@ -77,40 +86,44 @@ func (s *LomsService) OrderCreate(ctx context.Context, orderReq *pb.OrderCreateR return int(a.ID - b.ID) }) - id, err := s.orders.OrderCreate(ctx, order) - if err != nil { - return 0, fmt.Errorf("orders.OrderCreate: %w", err) - } + var ( + orderID entity.ID + resErr error + ) - order.OrderID = id - - commitedStocks := make([]*entity.Stock, 0, len(order.Items)) - for _, item := range order.Items { - stock := &entity.Stock{ - Item: item, - Reserved: item.Count, + err := s.txManager.WriteWithTransaction(ctx, func(txCtx context.Context) error { + id, err := s.orders.OrderCreate(txCtx, order) + if err != nil { + return err } + order.OrderID = id + orderID = id - if err := s.stocks.StockReserve(ctx, stock); err != nil { - s.rollbackStocks(ctx, commitedStocks) + committed := make([]*entity.Stock, 0, len(order.Items)) + for _, it := range order.Items { + st := &entity.Stock{Item: it, Reserved: it.Count} + if err := s.stocks.StockReserve(txCtx, st); err != nil { + s.rollbackStocks(txCtx, committed) - if statusErr := s.orders.OrderSetStatus(ctx, order.OrderID, pb.OrderStatus_ORDER_STATUS_FAILED.String()); statusErr != nil { - log.Error().Err(statusErr).Msg("failed to update status on stock reserve fail") + _ = s.orders.OrderSetStatus(txCtx, id, + pb.OrderStatus_ORDER_STATUS_FAILED.String()) + + resErr = fmt.Errorf("stocks.StockReserve: %w", err) + return nil } - - return 0, fmt.Errorf("stocks.StockReserve: %w", err) + committed = append(committed, st) } - commitedStocks = append(commitedStocks, stock) - } - - if err := s.orders.OrderSetStatus(ctx, order.OrderID, pb.OrderStatus_ORDER_STATUS_AWAITING_PAYMENT.String()); err != nil { - s.rollbackStocks(ctx, commitedStocks) - + return s.orders.OrderSetStatus(txCtx, id, + pb.OrderStatus_ORDER_STATUS_AWAITING_PAYMENT.String()) + }) + if err != nil { return 0, err } - - return order.OrderID, nil + if resErr != nil { + return 0, resErr + } + return orderID, nil } func (s *LomsService) OrderInfo(ctx context.Context, orderID entity.ID) (*entity.Order, error) { @@ -122,54 +135,66 @@ func (s *LomsService) OrderInfo(ctx context.Context, orderID entity.ID) (*entity } func (s *LomsService) OrderPay(ctx context.Context, orderID entity.ID) error { - order, err := s.OrderInfo(ctx, orderID) - if err != nil { - return err + if orderID <= 0 { + return model.ErrInvalidInput } - switch order.Status { - case pb.OrderStatus_ORDER_STATUS_PAYED.String(): - return nil - case pb.OrderStatus_ORDER_STATUS_AWAITING_PAYMENT.String(): - for _, item := range order.Items { - if err := s.stocks.StockReserveRemove(ctx, &entity.Stock{ - Item: item, - Reserved: item.Count, - }); err != nil { - log.Error().Err(err).Msg("failed to free stock reservation") - } + return s.txManager.WriteWithTransaction(ctx, func(txCtx context.Context) error { + order, err := s.orders.OrderGetByID(txCtx, orderID) + if err != nil { + return err } - return s.orders.OrderSetStatus(ctx, orderID, pb.OrderStatus_ORDER_STATUS_PAYED.String()) - default: - return model.ErrOrderInvalidStatus - } + switch order.Status { + case pb.OrderStatus_ORDER_STATUS_PAYED.String(): + return nil + case pb.OrderStatus_ORDER_STATUS_AWAITING_PAYMENT.String(): + for _, it := range order.Items { + if err := s.stocks.StockReserveRemove(txCtx, &entity.Stock{ + Item: it, + Reserved: it.Count, + }); err != nil { + log.Error().Err(err).Msg("failed to free stock reservation") + } + } + return s.orders.OrderSetStatus(txCtx, orderID, + pb.OrderStatus_ORDER_STATUS_PAYED.String()) + default: + return model.ErrOrderInvalidStatus + } + }) } func (s *LomsService) OrderCancel(ctx context.Context, orderID entity.ID) error { - order, err := s.OrderInfo(ctx, orderID) - if err != nil { - return err + if orderID <= 0 { + return model.ErrInvalidInput } - switch order.Status { - case pb.OrderStatus_ORDER_STATUS_CANCELLED.String(): - return nil - case pb.OrderStatus_ORDER_STATUS_FAILED.String(), pb.OrderStatus_ORDER_STATUS_PAYED.String(): - return model.ErrOrderInvalidStatus - } - - stocks := make([]*entity.Stock, len(order.Items)) - for i, item := range order.Items { - stocks[i] = &entity.Stock{ - Item: item, - Reserved: item.Count, + return s.txManager.WriteWithTransaction(ctx, func(txCtx context.Context) error { + order, err := s.orders.OrderGetByID(txCtx, orderID) + if err != nil { + return err } - } - s.rollbackStocks(ctx, stocks) + switch order.Status { + case pb.OrderStatus_ORDER_STATUS_CANCELLED.String(): + return nil + case pb.OrderStatus_ORDER_STATUS_FAILED.String(), + pb.OrderStatus_ORDER_STATUS_PAYED.String(): + return model.ErrOrderInvalidStatus + } - return s.orders.OrderSetStatus(ctx, orderID, pb.OrderStatus_ORDER_STATUS_CANCELLED.String()) + for _, it := range order.Items { + if err := s.stocks.StockCancel(txCtx, &entity.Stock{ + Item: it, + Reserved: it.Count, + }); err != nil { + return err + } + } + return s.orders.OrderSetStatus(txCtx, orderID, + pb.OrderStatus_ORDER_STATUS_CANCELLED.String()) + }) } func (s *LomsService) StocksInfo(ctx context.Context, sku entity.Sku) (uint32, error) { @@ -182,5 +207,5 @@ func (s *LomsService) StocksInfo(ctx context.Context, sku entity.Sku) (uint32, e return 0, err } - return stock.Item.Count, nil + return stock.Item.Count - stock.Reserved, nil } diff --git a/loms/internal/domain/service/service_test.go b/loms/internal/domain/service/service_test.go index c5af63f..86316e9 100644 --- a/loms/internal/domain/service/service_test.go +++ b/loms/internal/domain/service/service_test.go @@ -21,6 +21,24 @@ const ( testSku = entity.Sku(199) ) +type mockTxManager struct{} + +func (t *mockTxManager) WriteWithTransaction(ctx context.Context, fn func(ctx context.Context) error) (err error) { + return fn(ctx) +} + +func (t *mockTxManager) ReadWithTransaction(ctx context.Context, fn func(ctx context.Context) error) (err error) { + return fn(ctx) +} + +func (t *mockTxManager) WriteWithRepeatableRead(ctx context.Context, fn func(ctx context.Context) error) (err error) { + return fn(ctx) +} + +func (t *mockTxManager) ReadWithRepeatableRead(ctx context.Context, fn func(ctx context.Context) error) (err error) { + return fn(ctx) +} + func TestLomsService_OrderCreate(t *testing.T) { t.Parallel() @@ -130,8 +148,7 @@ func TestLomsService_OrderCreate(t *testing.T) { OrderCreateMock.Return(1, nil). OrderSetStatusMock.Return(errors.New("unexpected error")), stocks: mock.NewStockRepositoryMock(mc). - StockReserveMock.Return(nil). - StockCancelMock.Return(nil), + StockReserveMock.Return(nil), }, args: args{ req: goodReq, @@ -145,7 +162,7 @@ func TestLomsService_OrderCreate(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - svc := NewLomsService(tt.fields.orders, tt.fields.stocks) + svc := NewLomsService(tt.fields.orders, tt.fields.stocks, &mockTxManager{}) _, err := svc.OrderCreate(ctx, tt.args.req) tt.wantErr(t, err) }) @@ -256,24 +273,46 @@ func TestLomsService_OrderPay(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - svc := NewLomsService(tt.fields.orders, tt.fields.stocks) + svc := NewLomsService(tt.fields.orders, tt.fields.stocks, &mockTxManager{}) err := svc.OrderPay(ctx, tt.args.id) tt.wantErr(t, err) }) } } -func TestLomsService_OrderInfo(t *testing.T) { +func TestLomsService_OrderInfoBadInput(t *testing.T) { t.Parallel() + svc := NewLomsService( + nil, + nil, + &mockTxManager{}, + ) + + _, err := svc.OrderInfo(context.Background(), 0) + require.ErrorIs(t, err, model.ErrInvalidInput) +} + +func TestLomsService_OrderInfoSuccess(t *testing.T) { + t.Parallel() + + order := &entity.Order{ + OrderID: 123, + Status: "payed", + UserID: 1337, + Items: []entity.OrderItem{}, + } + mc := minimock.NewController(t) svc := NewLomsService( - mock.NewOrderRepositoryMock(mc), - mock.NewStockRepositoryMock(mc), + mock.NewOrderRepositoryMock(mc).OrderGetByIDMock.Return(order, nil), + nil, + &mockTxManager{}, ) - err := svc.OrderPay(context.Background(), 0) - require.ErrorIs(t, err, model.ErrInvalidInput) + gotOrder, err := svc.OrderInfo(context.Background(), 123) + require.NoError(t, err) + require.Equal(t, order, gotOrder) } func TestLomsService_OrderCancel(t *testing.T) { @@ -370,7 +409,7 @@ func TestLomsService_OrderCancel(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - svc := NewLomsService(tt.fields.orders, tt.fields.stocks) + svc := NewLomsService(tt.fields.orders, tt.fields.stocks, &mockTxManager{}) err := svc.OrderCancel(ctx, tt.args.id) tt.wantErr(t, err) }) @@ -437,7 +476,7 @@ func TestLomsService_StocksInfo(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - svc := NewLomsService(nil, tt.fields.stocks) + svc := NewLomsService(nil, tt.fields.stocks, &mockTxManager{}) got, err := svc.StocksInfo(ctx, tt.args.sku) tt.wantErr(t, err) if err == nil { diff --git a/loms/internal/infra/postgres/postgres.go b/loms/internal/infra/postgres/postgres.go new file mode 100644 index 0000000..e8902b6 --- /dev/null +++ b/loms/internal/infra/postgres/postgres.go @@ -0,0 +1,56 @@ +package postgres + +import ( + "context" + + "github.com/jackc/pgx/v5/pgxpool" + "github.com/pkg/errors" +) + +// From https://gitlab.ozon.dev/go/classroom-18/students/week-4-workshop/-/blob/master/internal/infra/postgres/postgres.go + +func NewPool(ctx context.Context, dsn string) (*pgxpool.Pool, error) { + config, err := pgxpool.ParseConfig(dsn) + if err != nil { + return nil, errors.Wrap(err, "pgxpool.ParseConfig") + } + + pool, err := pgxpool.NewWithConfig(ctx, config) + if err != nil { + return nil, errors.Wrap(err, "pgxpool.NewWithConfig") + } + + return pool, nil +} + +func NewPools(ctx context.Context, DSNs ...string) ([]*pgxpool.Pool, error) { + pools := make([]*pgxpool.Pool, len(DSNs)) + + for i, dsn := range DSNs { + cfg, err := pgxpool.ParseConfig(dsn) + if err != nil { + closeOpened(pools[:i]) + + return nil, errors.Wrap(err, "pgxpool.ParseConfig") + } + + pool, err := pgxpool.NewWithConfig(ctx, cfg) + if err != nil { + closeOpened(pools[:i]) + + return nil, errors.Wrap(err, "pgxpool.NewWithConfig") + } + + pools[i] = pool + } + + return pools, nil +} + +func closeOpened(pools []*pgxpool.Pool) { + for _, p := range pools { + if p != nil { + p.Close() + } + } +} diff --git a/loms/internal/infra/postgres/tx.go b/loms/internal/infra/postgres/tx.go new file mode 100644 index 0000000..5244abd --- /dev/null +++ b/loms/internal/infra/postgres/tx.go @@ -0,0 +1,87 @@ +package postgres + +// From https://gitlab.ozon.dev/go/classroom-18/students/week-4-workshop/-/blob/master/internal/infra/postgres/tx.go + +import ( + "context" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgxpool" + "github.com/opentracing/opentracing-go" +) + +// Tx транзакция. +type Tx pgx.Tx + +type txKey struct{} + +func ctxWithTx(ctx context.Context, tx pgx.Tx) context.Context { + return context.WithValue(ctx, txKey{}, tx) +} + +func TxFromCtx(ctx context.Context) (pgx.Tx, bool) { + tx, ok := ctx.Value(txKey{}).(pgx.Tx) + + return tx, ok +} + +type TxManager struct { + write *pgxpool.Pool + read *pgxpool.Pool +} + +func NewTxManager(write, read *pgxpool.Pool) *TxManager { + return &TxManager{ + write: write, + read: read, + } +} + +// WithTransaction выполняет fn в транзакции с дефолтным уровнем изоляции. +func (m *TxManager) WriteWithTransaction(ctx context.Context, fn func(ctx context.Context) error) (err error) { + return m.withTx(ctx, m.write, pgx.TxOptions{}, fn) +} + +func (m *TxManager) ReadWithTransaction(ctx context.Context, fn func(ctx context.Context) error) (err error) { + return m.withTx(ctx, m.read, pgx.TxOptions{}, fn) +} + +// WithTransaction выполняет fn в транзакции с уровнем изоляции RepeatableRead. +func (m *TxManager) WriteWithRepeatableRead(ctx context.Context, fn func(ctx context.Context) error) (err error) { + return m.withTx(ctx, m.write, pgx.TxOptions{IsoLevel: pgx.RepeatableRead}, fn) +} + +func (m *TxManager) ReadWithRepeatableRead(ctx context.Context, fn func(ctx context.Context) error) (err error) { + return m.withTx(ctx, m.read, pgx.TxOptions{IsoLevel: pgx.RepeatableRead}, fn) +} + +// WithTx выполняет fn в транзакции. +func (m *TxManager) withTx(ctx context.Context, pool *pgxpool.Pool, options pgx.TxOptions, fn func(ctx context.Context) error) (err error) { + var span opentracing.Span + span, ctx = opentracing.StartSpanFromContext(ctx, "Transaction") + defer span.Finish() + + tx, err := pool.BeginTx(ctx, options) + if err != nil { + return + } + ctx = ctxWithTx(ctx, tx) + + defer func() { + if p := recover(); p != nil { + // a panic occurred, rollback and repanic + _ = tx.Rollback(ctx) + panic(p) + } else if err != nil { + // something went wrong, rollback + _ = tx.Rollback(ctx) + } else { + // all good, commit + err = tx.Commit(ctx) + } + }() + + err = fn(ctx) + + return +} diff --git a/loms/internal/infra/tools/safecast.go b/loms/internal/infra/tools/safecast.go new file mode 100644 index 0000000..5849d74 --- /dev/null +++ b/loms/internal/infra/tools/safecast.go @@ -0,0 +1,19 @@ +package tools + +import ( + "fmt" + "math" +) + +func SafeCastInt64ToUInt32(num int64) (uint32, error) { + if num < 0 { + return 0, fmt.Errorf("tried casting signed negative number to unsigned number") + } + + if num > math.MaxUint32 { + return 0, fmt.Errorf("tried casting larger number than uint32 can store") + } + + // the bounds are checked, and cast should be safe. + return uint32(num), nil // #nosec G115 +} diff --git a/loms/sqlc.yaml b/loms/sqlc.yaml new file mode 100644 index 0000000..d52d204 --- /dev/null +++ b/loms/sqlc.yaml @@ -0,0 +1,28 @@ +version: "2" +sql: + - engine: "postgresql" + queries: "internal/domain/repository/orders/sqlc/query.sql" + schema: "db/migrations" + gen: + go: + package: "sqlc" + out: "internal/domain/repository/orders/sqlc" + sql_package: "pgx/v5" + emit_interface: true + emit_pointers_for_null_types: true + emit_result_struct_pointers: true + emit_params_struct_pointers: true + omit_unused_structs: true + - engine: "postgresql" + queries: "internal/domain/repository/stocks/sqlc/query.sql" + schema: "db/migrations" + gen: + go: + package: "sqlc" + out: "internal/domain/repository/stocks/sqlc" + sql_package: "pgx/v5" + emit_interface: true + emit_pointers_for_null_types: true + emit_result_struct_pointers: true + emit_params_struct_pointers: true + omit_unused_structs: true diff --git a/loms/tests/integration/loms_integration_test.go b/loms/tests/integration/loms_integration_test.go index 8109044..2c0002a 100644 --- a/loms/tests/integration/loms_integration_test.go +++ b/loms/tests/integration/loms_integration_test.go @@ -5,20 +5,27 @@ package integration import ( "context" + "database/sql" + "fmt" "net" "testing" "time" + "github.com/jackc/pgx/v5/pgxpool" "github.com/ozontech/allure-go/pkg/framework/provider" "github.com/ozontech/allure-go/pkg/framework/suite" + "github.com/pressly/goose/v3" + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "route256/loms/internal/app/server" "route256/loms/internal/domain/entity" - ordersRepository "route256/loms/internal/domain/repository/orders" - stocksRepository "route256/loms/internal/domain/repository/stocks" + ordersRepository "route256/loms/internal/domain/repository/orders/sqlc" + stocksRepository "route256/loms/internal/domain/repository/stocks/sqlc" lomsService "route256/loms/internal/domain/service" + "route256/loms/internal/infra/postgres" pb "route256/pkg/api/loms/v1" ) @@ -28,16 +35,77 @@ const ( // "reserved": 35 testSKU = entity.Sku(1076963) - testUID = entity.ID(1337) - testCount = uint32(2) + testUID = entity.ID(1337) + testCount = uint32(2) + migrationsDir = "../../db/migrations" ) +func startPostgres(ctx context.Context, migrationsDir string) (*pgxpool.Pool, func(), error) { + req := testcontainers.ContainerRequest{ + Image: "gitlab-registry.ozon.dev/go/classroom-18/students/base/postgres:16", + Env: map[string]string{ + "POSTGRESQL_USERNAME": "user", + "POSTGRESQL_PASSWORD": "postgres", + "POSTGRESQL_DATABASE": "loms_test", + "POSTGRESQL_PORT": "5437", + }, + ExposedPorts: []string{"5437/tcp"}, + WaitingFor: wait.ForListeningPort("5437/tcp").WithStartupTimeout(30 * time.Second), + } + container, err := testcontainers.GenericContainer(ctx, + testcontainers.GenericContainerRequest{ContainerRequest: req, Started: true}) + if err != nil { + return nil, nil, err + } + + endpoint, err := container.Endpoint(ctx, "") + if err != nil { + container.Terminate(ctx) + return nil, nil, err + } + + dsn := fmt.Sprintf("postgresql://user:postgres@%s/loms_test?sslmode=disable", endpoint) + + var pool *pgxpool.Pool + for i := 0; i < 30; i++ { + pool, err = pgxpool.New(ctx, dsn) + if err == nil && pool.Ping(ctx) == nil { + break + } + time.Sleep(1 * time.Second) + } + if err != nil { + container.Terminate(ctx) + return nil, nil, err + } + + std, err := sql.Open("pgx", dsn) + if err != nil { + container.Terminate(ctx) + return nil, nil, err + } + if err := goose.Up(std, migrationsDir); err != nil { + container.Terminate(ctx) + return nil, nil, err + } + std.Close() + + cleanup := func() { + pool.Close() + _ = container.Terminate(context.Background()) + } + return pool, cleanup, nil +} + type LomsIntegrationSuite struct { suite.Suite - grpcSrv *grpc.Server - grpcConn *grpc.ClientConn + grpcSrv *grpc.Server + grpcConn *grpc.ClientConn + lomsClient pb.LOMSClient + + cleanup func() } func TestLomsIntegrationSuite(t *testing.T) { @@ -45,12 +113,17 @@ func TestLomsIntegrationSuite(t *testing.T) { } func (s *LomsIntegrationSuite) BeforeAll(t provider.T) { + ctx := context.Background() t.WithNewStep("init cart-service", func(sCtx provider.StepCtx) { - orderRepo := ordersRepository.NewInMemoryRepository(100) - stockRepo, err := stocksRepository.NewInMemoryRepository(100) - sCtx.Require().NoError(err) + pool, cleanup, err := startPostgres(ctx, migrationsDir) + s.cleanup = cleanup - svc := lomsService.NewLomsService(orderRepo, stockRepo) + orderRepo := ordersRepository.NewOrderRepository(pool) + stockRepo := stocksRepository.NewStockRepository(pool, pool) + + txManager := postgres.NewTxManager(pool, pool) + + svc := lomsService.NewLomsService(orderRepo, stockRepo, txManager) lomsServer := server.NewServer(svc) lis, err := net.Listen("tcp", "127.0.0.1:0") @@ -74,6 +147,7 @@ func (s *LomsIntegrationSuite) BeforeAll(t provider.T) { func (s *LomsIntegrationSuite) AfterAll(t provider.T) { s.grpcSrv.Stop() _ = s.grpcConn.Close() + s.cleanup() } func (s *LomsIntegrationSuite) TestOrderProcessPositive(t provider.T) { diff --git a/make/bin-deps.mk b/make/bin-deps.mk new file mode 100644 index 0000000..cb8bb80 --- /dev/null +++ b/make/bin-deps.mk @@ -0,0 +1,31 @@ +CURDIR=$(shell pwd) +BINDIR=${CURDIR}/bin +GOVER=$(shell go version | perl -nle '/(go\d\S+)/; print $$1;') + +LINTVER=v1.60.3 +LINTBIN=bin/golangci-lint + +bindir: + mkdir -p ${BINDIR} + +.PHONY: .bin-deps +.bin-deps: bindir + $(info Installing binary dependencies...) + GOBIN=$(BINDIR) go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28.1 && \ + GOBIN=$(BINDIR) go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2.0 && \ + GOBIN=$(BINDIR) go install github.com/envoyproxy/protoc-gen-validate@v1.0.4 && \ + GOBIN=$(BINDIR) go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.19.1 && \ + GOBIN=$(BINDIR) go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@v2.19.1 && \ + GOBIN=$(BINDIR) go install github.com/go-swagger/go-swagger/cmd/swagger@v0.30.5 && \ + GOBIN=$(BINDIR) go install github.com/gojuno/minimock/v3/cmd/minimock@v3.4.0 + + $(info Installing golangci-lint...) + test -f ${LINTBIN} || \ + (GOBIN=${BINDIR} go install github.com/golangci/golangci-lint/cmd/golangci-lint@${LINTVER} && \ + mv ${BINDIR}/golangci-lint ${LINTBIN}) + + $(info Installing goose binary...) + GOBIN=$(BINDIR) go install github.com/pressly/goose/v3/cmd/goose@v3.24.1 + + $(info Installing sqlc binary...) + GOBIN=$(BINDIR) CGO_ENABLED=0 go install github.com/sqlc-dev/sqlc/cmd/sqlc@v1.29.0 diff --git a/make/generate.mk b/make/generate.mk index 8961c77..06fe317 100644 --- a/make/generate.mk +++ b/make/generate.mk @@ -1,17 +1,6 @@ CURDIR=$(shell pwd) BINDIR=${CURDIR}/bin -.PHONY: .bin-deps -.bin-deps: - $(info Installing binary dependencies...) - - GOBIN=$(BINDIR) go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28.1 && \ - GOBIN=$(BINDIR) go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2.0 && \ - GOBIN=$(BINDIR) go install github.com/envoyproxy/protoc-gen-validate@v1.0.4 && \ - GOBIN=$(BINDIR) go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.19.1 && \ - GOBIN=$(BINDIR) go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@v2.19.1 && \ - GOBIN=$(BINDIR) go install github.com/go-swagger/go-swagger/cmd/swagger@v0.30.5 - # Устанавливаем proto описания google/protobuf vendor-proto/google/protobuf: git clone -b main --single-branch -n --depth=1 \ @@ -69,7 +58,7 @@ define generate echo "no internal package in $(1)"; \ exit 0; \ fi; \ - go generate ./$(1)/internal/...; \ + PATH=$(PATH):$(BINDIR) go generate ./$(1)/internal/...; \ fi endef diff --git a/make/lint.mk b/make/lint.mk index f81d3c2..36e04f5 100644 --- a/make/lint.mk +++ b/make/lint.mk @@ -1,19 +1,6 @@ -CURDIR=$(shell pwd) -BINDIR=${CURDIR}/bin GOVER=$(shell go version | perl -nle '/(go\d\S+)/; print $$1;') -LINTVER=v1.60.3 LINTBIN=bin/golangci-lint - -bindir: - mkdir -p ${BINDIR} - - -install-lint: bindir - test -f ${LINTBIN} || \ - (GOBIN=${BINDIR} go install github.com/golangci/golangci-lint/cmd/golangci-lint@${LINTVER} && \ - mv ${BINDIR}/golangci-lint ${LINTBIN}) - define lint @if [ -f "$(1)/go.mod" ]; then \ output=$$(${LINTBIN} --config=.golangci.yaml run $(1)/... 2>&1); \