OrderService: бронирование с ретраями, блокировка пользователя, квитанция

Код-ревьюMiddle30 минпроверка — Спринт23-t006

Отревьюйте и исправьте сервис OrderService.PlaceOrder: он блокирует пользователя, бронирует через внешнего провайдера (повторяя попытку, если ошибка помечена как retryable), формирует квитанцию и снимает блокировку.

Как на собесе: 30 минут, ищи всё — гонки, утечки, ошибки, безопасность, стиль. Ссылайся на строки.

review.gogo
1package booking2 3import (4	"errors"5	"log"6	"time"7)8 9type OrderService struct {10	Booking BookingProvider11	Users   UserLocker12}13 14type UserLocker interface {15	Lock(User) error16	Unlock(User) error17}18 19type User struct {20	ID string21}22 23type Receipt struct {24	ID       string25	Code     string26	BookedAt string27}28 29type BookingProvider interface {30	Book() (string, *BookingError)31}32 33type BookingError struct {34	error35	Retryable bool36}37 38func (s *OrderService) PlaceOrder(user User) (res *Receipt, err error) {39	receipt := Receipt{ID: "generated"}40 41	if err := s.Users.Lock(user); err != nil {42		log.Println(err)43		return nil44	}45	for {46		code, err := s.Booking.Book()47		if errors.Is(err, err.Retryable) {48				/////49		}50 51		switch {52		case err == nil:53			receipt.BookedAt = time.Now().Format(time.RFC3339)54			receipt.Code = code55			return &receipt56		case err.Retryable:57		default:58			log.Println(err)59			break60		}61	}62	if err := s.Users.Unlock(user); err != nil {63		log.Println(err)64		return nil65	}66 67	return &receipt68}
⌘ Enter — проверить