slotline

Платформа бронирования ресурсов (залы, корты, оборудование) на Spring Boot. Ядро гарантирует, что один слот никогда не будет забронирован дважды - даже при высокой параллельности.

slotline
TL;DR

Платформа бронирования ресурсов (залы, корты, оборудование) на Spring Boot. Выглядит банально, пока два человека не кликнут по одному и тому же слоту в одну и ту же миллисекунду. Ядро гарантирует, что один слот никогда не будет забронирован дважды, даже при высокой параллельности.

Введение

Бронирование слота на первый взгляд выглядит как вставка строки, и многие разработчики так его и пишут. Беда в том, что настоящая трудность не в типичном случае, а в той одной миллисекунде, когда два человека тянутся к одному и тому же свободному слоту. slotline построен вокруг этой одной миллисекунды, а не вокруг формы бронирования.

Все остальное в платформе - ресурсы, календарь и представления - обрамляет одну гарантию: что у слота есть ровно один победитель. Именно это решает, серьезна ли система или лишь выглядит работающей до первой толпы.

Вся трудность сидит в одной миллисекунде

Наивная реализация делает два шага: проверяет, свободен ли слот, а затем записывает его. Между этими шагами есть щель, в которой второй пользователь успевает увидеть тот же слот свободным. Оба проходят проверку, оба записывают, и у вас две брони на один слот, о которых никто не знал, что они возможны.

slotline относится к этому как к главной проблеме, которую надо решить, а не как к краевому случаю. Доменная модель понятна именно для того, чтобы эта одна гарантия была очевидна при чтении кода, а не спрятана где-то в сервисном слое.

!
Внимание

Проверка доступности и запись брони - это не две отдельные операции. Если это так, у вас гонка. Гарантию дает база, через уникальное ограничение на ресурс и временной интервал, а не проверка в коде приложения.

schema.sql · sql
ALTER TABLE booking
  ADD CONSTRAINT uq_slot UNIQUE (resource_id, starts_at);

Уникальное ограничение переносит разрешение в единственное место, где параллельность действительно сериализуется: в движок базы. Неважно, сколько пользователей кликает разом, потому что победителя определяет атомарная запись, а проигравшие получают чистую ошибку конфликта вместо тихой двойной брони.

Тест, который действительно может упасть

Легко написать тест, который бронирует один раз и проверяет, что получилось. Это ничего не доказывает, потому что он не касается условия, которое должно держаться. Ценный тест запускает много потоков по одному и тому же слоту разом и проверяет, что выигрывает ровно один, а остальные получают чистую ошибку конфликта.

Одновременный штурм одного слота (ориентировочно)

Потоки, бьющие в слот
50
Записанные брони
1

Проверка контрфактическая: снимите уникальное ограничение, и тот же тест начинает пропускать две брони. Если после снятия защиты тест остается зеленым, он ничего не стерег.

Один победитель, всегда

Результат - платформа, которая под нагрузкой ведет себя точно так же, как при одном пользователе: у слота один владелец, и точка. Нет состояния, в котором два человека уходят с одним и тем же слотом, потому что такая возможность вырезана у источника, в базе, а не залатана в интерфейсе.

1
победитель на слот, всегда
0
двойных броней под нагрузкой

Больше проектов

Другие работы из той же категории - посмотрите, как мы решаем похожие задачи.

Есть похожий проект?

Напишите нам - смета бесплатна и приходит в течение часа.