Go: Сохраняем бронь и ищем по requestid — задача с проверкой

Практическая задача на Go по теме «Сохраняем бронь и ищем по request_id». Условие содержит контракт функций, предоставленные типы и требования к результату. Используйте выданный шаблон и сохраняйте его публичные объявления. Перед проверкой разберите успешный путь, обработку ошибок и отмену операции, когда она предусмотрена контрактом. Здесь оценивается конкретный компонент сервиса; в полном курсе микросервисов на Go эти компоненты связываются с HTTP, PostgreSQL, gRPC и Kafka.

Сохраняем бронь и ищем по request_id

Вам нужно реализовать две функции для работы с системой бронирования мест.

Проверка передаёт fake-репозиторий BookingRepository, который возвращает данные и уже переведённые доменные ошибки. Здесь проверяется сервисный маппинг результата и ошибок; SQL, PostgreSQL, драйвер, сеть и внешние модули не нужны.

Типы и сентинели, уже объявлены — не переопределяйте их:


type Booking struct {
    ID         int64
    ShowID     int64
    SeatNo     int32
    CustomerID int64
    RequestID  string
}

type BookingRepository interface {
    Insert(context.Context, Booking) (Booking, error)
    ByRequestID(context.Context, string) (Booking, error)
}

type Result struct {
    Status  string
    Booking Booking
}

var ErrConflict = errors.New("booking conflict")
var ErrNotFound = errors.New("booking not found")

Реализуйте ровно две функции:

Дополните TODO в редакторе и отправьте весь код, сохранив package main, импорты, предоставленные типы и публичную функцию RunScenario. Не добавляйте свою функцию main: JSON-адаптер запуска платформа добавит сама. Скрытые входы и ожидаемые результаты находятся на стороне проверки.


func CreateBooking(ctx context.Context, repo BookingRepository, in Booking) Result
func FindBooking(ctx context.Context, repo BookingRepository, requestID string) Result

Правила маппинга для CreateBooking:

  • Вызовите repo.Insert(ctx, in) — ровно один раз, с теми же ctx и in.
  • Ошибки нет → Result{Status: "created", Booking: <возвращённый репозиторием Booking>}.
  • Ошибка — ErrConflict (прямая или обёрнутая через %w) → Result{Status: "conflict"}.
  • Любая другая ненулевая ошибка → Result{Status: "storage_error"}.

Правила маппинга для FindBooking:

  • Вызовите repo.ByRequestID(ctx, requestID) — ровно один раз.
  • Ошибки нет → Result{Status: "found", Booking: <возвращённый репозиторием Booking>}.
  • Ошибка — ErrNotFound (прямая или обёрнутая через %w) → Result{Status: "not_found"}.
  • Любая другая ненулевая ошибка → Result{Status: "storage_error"}.

Общие правила:

  • При любой ошибке поле Booking в Result должно быть нулевым (Booking{}), даже если репозиторий вернул ненулевое значение.
  • ErrNotFound в CreateBooking и ErrConflict в FindBooking считаются storage_error.
  • Никаких повторных вызовов, дополнительных запросов, retry-логики.
  • Совпадение текста ошибки не считается совпадением сентинеля — важна идентичность через errors.Is.

Подсказки

  • Для проверки типа ошибки используйте errors.Is(err, ErrConflict) / errors.Is(err, ErrNotFound) — это корректно обработает как прямые ошибки, так и обёрнутые через fmt.Errorf("%w", ...).
  • Присваивайте Booking в Result только из значения, возвращённого репозиторием, и только когда err == nil; во всех остальных случаях оставляйте поле нулевым.
РешениеGo

Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.

Отправьте решение, чтобы увидеть результаты тестов.

Связанные задачи