Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

complete http part of gophermart #1

Merged
merged 52 commits into from
Oct 22, 2023
Merged

complete http part of gophermart #1

merged 52 commits into from
Oct 22, 2023

Conversation

MowlCoder
Copy link
Owner

No description provided.

@MowlCoder
Copy link
Owner Author

MowlCoder commented Oct 3, 2023

В этой версии я закончил все запросы из части про Gophermart, и пока не делал расчёт награды за каждый заказ, как раз буду приступать после этой части, хотелось бы чтобы отсмотрели архитектурные моменты, чтобы пока далеко не ушёл - исправить их

authHandler := handlers.NewAuthHandler(&handlers.AuthHandlerOptions{
UserService: userService,
})
balanceHandler := handlers.NewBalanceHandler(&handlers.BalanceHandlerOptions{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а зачем тут везде Options? почему не прокинуть просто как зависимости?


func (w *CalculateOrderAccrualWorker) Start(ctx context.Context) {
log.Println("Start calculate_order_accrual worker")
ticker := time.NewTicker(time.Second * 5)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

тикер не закрыт

continue
}

for _, order := range orders {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

зачем тут горутина в горутине?

log.Println("[checking_order_accrual] putting worker to rest for", seconds, "seconds")

w.isResting = true
timer := time.NewTimer(time.Second * time.Duration(seconds))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а зачем тут это? и тут не надо локи? если у тебя это в горутинах


err = w.balanceActionRepository.Save(ctx, order.UserID, order.OrderID, *orderInfo.Accrual)

if err != nil {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

не критикал, но получается может выполниться запрос SetOrderCalculatingResult? но потом balanceActionRepository.Save моожет не сохранить, тут целостность данных не ломается? как это потом будет обработано?

return
}

err = w.balanceActionRepository.Save(ctx, order.UserID, order.OrderID, *orderInfo.Accrual)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а если *orderInfo.Accrual будет nil?

}

func (w *OrderAccrualCheckingWorker) processOrder(ctx context.Context, order *domain.UserOrder) {
orderInfo, err := w.getInfoFromAccrualSystem(order.OrderID)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а если order nil?

r.Post("/register", authHandler.Register)
r.Post("/login", authHandler.Login)

r.Get("/orders", middlewares.AuthMiddleware(http.HandlerFunc(ordersHandler.GetOrders)))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

можно сделать r.Group и внутри использовать сразу один раз middleware


for _, order := range orders {
go func(o domain.UserOrder) {
go w.processOrder(ctx, &o)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

вот тут зачем горутина в горутине, я не там написал

SetOrderCalculatingResult(ctx context.Context, orderID string, status string, accrual float64) error
}

type OrderAccrualFacade struct {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Этот фасад теперь вроде не нужен?

userOrderRepository,
orderAccrualFacade,
appConfig.AccrualSystemAddress,
workersWg,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

хорошей практикой когда вся работа с waitGroup в одном файле, поэтому рекомендую так не делать
сейчас работа с wg размазана по всему файлу, не прозрачно получается

log.Fatal(err)
}

dbPool.Close()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

лучше поднять к месту где инициализируется и сделать в defer, чтобы было рядом

ticker := time.NewTicker(time.Second * 5)

go func() {
defer ticker.Stop()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

почему в горутине?

if err != nil {
var retryAfterError domain.RetryAfterError
if errors.As(err, &retryAfterError) {
ticker.Reset(time.Second * time.Duration(retryAfterError.Seconds))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

лучше тикер двигать не в каждой горутине, а использовать пакет errgroup например или самому сделать аналог, получил ошибку - остановил или дал отработать остальным горутинам и уже после подвинул тикер


log.Println("Start checking_order_accrual worker")
ticker := time.NewTicker(baseTickerDuration)
w.wg.Add(1)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а зачем тут это?

}
}

func (w *OrderAccrualCheckingWorker) Start(ctx context.Context) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Написал тест на эту функцию и запустил с флагом -race

Снимок экрана 2023-10-14 в 23 41 31

спойлерить не буду, попробуй сам найти

)

type BalanceActionRepoMock struct {
Storage []domain.BalanceAction

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Такой подход не очень практичный

  1. Все пакеты становятся завязанные на пакет mocks
  2. Мок содержит в себе много функций
  3. Попробуй запустить тесты параллельно, у тебя тут хранится стейт, к чему это приведет?

очень рекомендую убрать моки в каждый пакет и моки сделать через mockery или аналог, чтобы состояние мока можно было менять и задавать в кейсах

func (s *WithdrawalsService) WithdrawBalance(ctx context.Context, userID int, orderID string, amount float64) error {
userBalance := s.balanceActionRepository.GetCurrentBalance(ctx, userID)

if userBalance-amount < 0 {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ты получил userBalance раньше, а тут проверяешь, но ведь в этот момент кто-то уже мог изменить баланс, и теперь он в базе будет с новым значением а эта проверка пройдет, я правильно понимаю?

@MowlCoder MowlCoder merged commit 04415f7 into master Oct 22, 2023
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants