Два пассажира, одно место, никаких двойных броней
Система бронирования автобусов с живой схемой мест. Когда двое хватают одно место в один момент, достаётся оно только одному.
Командный семестровый проект на ČVUT FEL, авторы — Mykhailo Plokhin и Ivan Shestachenko. Это демо, а не настоящий перевозчик.
Java · Spring Boot · PostgreSQL · React · Docker · k3s


Задача
Системы бронирования ломаются ровно тогда, когда двое хотят одно и то же одновременно — а это и есть момент, когда бизнес зарабатывает.
- Если приложение сначала читает место, а потом записывает, два запроса могут оба увидеть его свободным и оба его забронировать.
- Овербукинг часто чинят задним числом ночным скриптом и извинениями, вместо того чтобы сделать его невозможным.
- Пассажиру и диспетчеру нужны разные права, а не один эндпоинт за разными экранами.
Как устроено
Бронированиями владеет один сервис, и больше никто не пишет места. Спорное место проходит через одну короткую транзакцию с блокировкой строки.

Пассажир A бронирует место 12. База блокирует эту строку.
Пассажир B в тот же момент просит место 12 и ждёт, пока блокировка снимется.
Бронь A сохраняется. B получает «место занято», а не двойную бронь.
Ключевые решения
Каждое решение и альтернатива, которую оно обошло.
Блокировать строку спорного места
Второй запрос ждёт, а не перезаписывает, и ждёт недолго: удержание места — единственная работа внутри транзакции. Альтернативой были оптимистичные повторы; на полном рейсе они превращаются в лавину повторов.
Один путь записи для броней
Расписание, схема мест и диспетчер только читают. С одним писателем правило «одно место — один пассажир» система может реально проверить.
Роли проверяются на эндпоинте
Spring Security определяет роль до обработчика, поэтому действие диспетчера недоступно с URL пассажира.
Цифры
Omnibus — университетский проект с живым демо, а не коммерческий сервис. «Проверено» значит проверено в коде; «цель» — на что система рассчитана.
| Показатель | Что значит | Основание |
|---|---|---|
| ZeroДвойные брони | Цель системы: второго писателя отклоняет база, а не ночной скрипт потом.Цель | Цель |
| FOR UPDATEБлокировка места | Пессимистическая блокировка строки в запросе места (BookedSegmentRepository).Проверено | Проверено |
| k3sГде работает | Контейнеры на кластере k3s — адрес по ссылке на этой странице.Проверено | Проверено |
- Цель
- — На что рассчитана система — не измеренный результат
- Проверено
- — Проверено в коде или на рабочей версии
Нужно что-то похожее?
Опишите задачу в паре строк. Ответит человек из команды.
Обсудить проект

