[hw-6] add notifier service, kafka

This commit is contained in:
Никита Шубин
2025-07-17 19:20:27 +00:00
parent 424d6905da
commit 6e1ad86128
33 changed files with 1412 additions and 92 deletions

View File

@@ -8,6 +8,7 @@ import (
"database/sql"
"fmt"
"net"
"sync"
"testing"
"time"
@@ -18,9 +19,10 @@ import (
"github.com/pressly/goose/v3"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
"go.uber.org/goleak"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/status"
"route256/loms/internal/app/server"
"route256/loms/internal/domain/entity"
@@ -42,6 +44,13 @@ const (
migrationsDir = "../../db/migrations"
)
// TODO: drop, use actual kafka for tests.
type mockKafkaProducer struct{}
func (kp mockKafkaProducer) Send(_ context.Context, id entity.ID, status string) error {
return nil
}
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",
@@ -111,8 +120,6 @@ type LomsIntegrationSuite struct {
}
func TestLomsIntegrationSuite(t *testing.T) {
defer goleak.VerifyNone(t)
suite.RunSuite(t, new(LomsIntegrationSuite))
}
@@ -129,7 +136,7 @@ func (s *LomsIntegrationSuite) BeforeAll(t provider.T) {
txManager := postgres.NewTxManager(pool, pool)
svc := lomsService.NewLomsService(orderRepo, stockRepo, txManager)
svc := lomsService.NewLomsService(orderRepo, stockRepo, txManager, &mockKafkaProducer{})
lomsServer := server.NewServer(svc)
lis, err := net.Listen("tcp", "127.0.0.1:0")
@@ -208,3 +215,122 @@ func (s *LomsIntegrationSuite) TestStocksInfoPositive(t provider.T) {
sCtx.Require().Greater(resp.Count, uint32(0))
})
}
func (s *LomsIntegrationSuite) TestOrderCreate_SuccessAsync(t provider.T) {
t.Title("Успешное создание заказов (async)")
const (
sku = 1625903
count = 1
ordersCount = 100
)
var (
userIDs = []int64{42, 43, 44}
orders = make([]struct {
userID int64
orderID int64
}, ordersCount)
initStocksCount uint64
ctx = context.Background()
)
t.WithNewStep("Получение изначальных стоков", func(sCtx provider.StepCtx) {
stockCount, err := s.lomsClient.StocksInfo(ctx, &pb.StocksInfoRequest{Sku: sku})
sCtx.Require().NoError(err)
initStocksCount = uint64(stockCount.GetCount())
})
t.WithNewStep("Создание заказов", func(sCtx provider.StepCtx) {
var wg sync.WaitGroup
for i := range ordersCount {
wg.Add(1)
go func() {
defer wg.Done()
userID := userIDs[i%len(userIDs)]
req := &pb.OrderCreateRequest{
UserId: userID,
Items: []*pb.OrderItem{
{
Sku: sku,
Count: count,
},
},
}
orderCreateResp, err := s.lomsClient.OrderCreate(ctx, req)
sCtx.Require().NoError(err)
sCtx.Require().Greater(orderCreateResp.OrderId, int64(0))
orders[i].userID = userID
orders[i].orderID = orderCreateResp.OrderId
}()
}
wg.Wait()
})
t.WithNewStep("Проверка заказов", func(sCtx provider.StepCtx) {
for _, order := range orders {
res, err := s.lomsClient.OrderInfo(ctx, &pb.OrderInfoRequest{
OrderId: order.orderID,
})
sCtx.Require().NoError(err)
expected := entity.Order{
Status: "awaiting payment",
UserID: entity.ID(order.userID),
Items: []entity.OrderItem{
{
ID: sku,
Count: count,
},
},
}
sCtx.Require().Equal(expected.Status, res.Status, "Не совпадает статус заказа")
sCtx.Require().Equal(expected.UserID, entity.ID(res.UserId), "Не совпадает пользователь заказа")
sCtx.Require().Equal(len(expected.Items), len(res.Items), "Не совпадает количество товаров в заказе")
}
})
t.WithNewStep("Проверка стоков", func(sCtx provider.StepCtx) {
stocksCount, err := s.lomsClient.StocksInfo(ctx, &pb.StocksInfoRequest{
Sku: sku,
})
sCtx.Require().NoError(err)
sCtx.Require().Equal(uint32(initStocksCount-ordersCount*count), stocksCount.Count)
})
}
func (s *LomsIntegrationSuite) TestOrderCreate_NoStockInfo(t provider.T) {
t.Title("Неуспешное создание заказ из-за отсутствия информации о стоках товара")
const (
userID = 42
sku = 404
)
ctx := context.Background()
t.WithNewStep("Создание заказа", func(sCtx provider.StepCtx) {
req := &pb.OrderCreateRequest{
UserId: userID,
Items: []*pb.OrderItem{
{
Sku: sku,
Count: 1,
},
},
}
_, err := s.lomsClient.OrderCreate(ctx, req)
e, ok := status.FromError(err)
sCtx.Require().True(ok)
sCtx.Require().Equal(codes.FailedPrecondition, e.Code(), "expect 400 (failed precondition) status code, got: %s", err.Error())
})
}