Войти Регистрация
Конкурентность

5. Резерв остатка товара на складе

Средняя

Go · 45 строк

Reserve вызывается при оформлении заказа, ReserveCart — для корзины из нескольких товаров. В распродажу по одному SKU приходит до 400 заказов в секунду.

Отметьте строки с ошибками.

В работе: Резервирование остатков при оформлении заказа.

Как проверяем Нажмите на строку с ошибкой и коротко напишите, что не так. Баг засчитан, если отмечена хотя бы одна его строка. Зачёт — найдено не меньше 60 % багов с учётом серьёзности (критичный весит 3, обычный 2, мелкий 1), а лишних отметок не больше, чем багов в коде. Пустые строки, скобки и комментарии лишними не считаем. Плюс 1 вопрос про поведение программы — на зачёт не влияют. Ответ один на подход: после него показываем разбор.
RWMutexcheck-then-actпотерянное обновление

Источник: на данных Ozon: склады и заказы. Условие пересказано своими словами.

Давали на собеседовании? Ответов пока мало — ваш поможет.
  1. package stock
  2. import (
  3. "errors"
  4. "sync"
  5. )
  6. var ErrOutOfStock = errors.New("товара нет на складе")
  7. type Warehouse struct {
  8. mu sync.RWMutex
  9. stock map[string]int // SKU → свободный остаток
  10. }
  11. // Reserve резервирует qty штук под заказ покупателя.
  12. func (w *Warehouse) Reserve(sku string, qty int) error {
  13. w.mu.RLock()
  14. left := w.stock[sku]
  15. w.mu.RUnlock()
  16. if left < qty {
  17. return ErrOutOfStock
  18. }
  19. w.mu.Lock()
  20. w.stock[sku] = left - qty
  21. w.mu.Unlock()
  22. return nil
  23. }
  24. // Release возвращает остаток при отмене заказа.
  25. func (w *Warehouse) Release(sku string, qty int) {
  26. w.mu.Lock()
  27. w.stock[sku] += qty
  28. w.mu.Unlock()
  29. }
  30. func (w *Warehouse) ReserveCart(items map[string]int) error {
  31. for sku, qty := range items {
  32. if err := w.Reserve(sku, qty); err != nil {
  33. return err
  34. }
  35. }
  36. return nil
  37. }