Обычная проверка «свободен ли номер?» может пропустить оба запроса: каждый успеет увидеть свободное время до сохранения чужой брони.
В PostgreSQL можно запретить пересечения прямо в базе:
CREATE EXTENSION IF NOT EXISTS btree_gist;
CREATE TABLE bookings (
room_id INT NOT NULL,
starts_at TIMESTAMPTZ NOT NULL,
ends_at TIMESTAMPTZ NOT NULL,
CHECK (ends_at > starts_at),
EXCLUDE USING gist (
room_id WITH =,
tstzrange(starts_at, ends_at, '[)') WITH &&
)
);
Как это работает:
•
room_id WITH = — проверяем брони одного номера.•
WITH && — запрещаем пересечение временных интервалов.•
'[)' — начало включено, конец исключён. Брони 10:00–11:00 и 11:00–12:00 допустимы.•
CHECK — окончание должно быть позже начала.Ограничение действует и при одновременных запросах. Две конфликтующие брони сохранить не получится: приложение должно обработать ошибку и сообщить, что время уже занято.
Подходит для гостиниц, переговорных, аренды оборудования и записи к специалистам.
