Nasze pierwsze narzędzie do rezerwacji sal powstało z bardzo zwyczajnego problemu. Klient dzwonił, ustalaliśmy termin, a później okazywało się, że brakuje informacji: o rzutniku, cateringu albo szczegółach zamówienia. Pamięć każdej ze stron bywała inna.
Formularz uporządkował zbieranie danych. Dostawaliśmy wiadomość z informacjami potrzebnymi do obsługi rezerwacji. Z tego rozwiązania wyrósł pomysł aplikacji bazodanowej, a później rozwój SmartRooms.
Formularz zbiera zgłoszenie. System musi jeszcze pilnować, co można obiecać klientowi.
Poprawne dane nie oznaczają dostępnego terminu
Walidacja potrafi sprawdzić, czy podano e-mail, wybrano salę i czy koniec wydarzenia wypada po jego początku. To potrzebne, ale nie wystarcza.
Wyobraź sobie dwóch klientów rezerwujących tę samą salę niemal jednocześnie. Obaj widzą wolny termin. Obaj klikają przycisk. Jeśli aplikacja najpierw sprawdza dostępność, a potem osobno zapisuje rezerwację, oba zgłoszenia mogą przejść przez sprawdzenie.
Zabezpieczenie musi działać również wtedy, gdy wiele osób korzysta z aplikacji naraz, a nie tylko podczas spokojnego klikania w testowym formularzu.
Baza danych może pilnować nakładających się terminów
Jedną z możliwości są przedziały czasu i ograniczenia wykluczające w PostgreSQL. Uproszczony przykład dla rezerwacji już zatwierdzonych:
CREATE EXTENSION IF NOT EXISTS btree_gist;
CREATE TABLE confirmed_reservation (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
room_id bigint 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 &&
)
);
Ograniczenie odrzuca zapis, jeśli dla tej samej sali istnieje nakładający się przedział. Zapis [) oznacza, że początek należy do przedziału, a koniec już nie. Rezerwacja kończąca się o 12:00 może więc sąsiadować z kolejną zaczynającą się o 12:00. Jeżeli potrzebny jest czas na przygotowanie sali, trzeba uwzględnić go w regułach dostępności.
To przykład mechanizmu. Pełny model musi jeszcze obsługiwać zmiany, anulowania, strefy czasowe oraz reguły konkretnego biznesu. Aplikacja powinna przechwycić konflikt i pokazać klientowi zrozumiałą informację, zamiast surowego błędu bazy.
Zgłoszenie, blokada i potwierdzenie
Warto od początku rozdzielić statusy. Zapytanie o termin może być niezobowiązującym zgłoszeniem. Tymczasowa blokada może czekać na płatność lub decyzję pracownika. Potwierdzona rezerwacja jest już zobowiązaniem.
Trzeba ustalić, które statusy zajmują salę i kiedy blokada wygasa. Bez tego kalendarz może pokazywać wolny termin, który ktoś właśnie kupuje, albo ukrywać termin zajęty przez dawno porzucone zgłoszenie.
Podobnie z powtórzonym kliknięciem. Jeśli przeglądarka ponowi żądanie po utracie połączenia, nie powinny powstać dwa zamówienia. Pomaga identyfikator operacji, po którym system rozpoznaje, że dane zgłoszenie już obsłużył.
E-mail jest powiadomieniem
W aplikacji bazodanowej stan rezerwacji powinien wynikać z zapisanego procesu. Wiadomość informuje o jego wyniku. Opóźnienie lub błąd wysyłki nie może sprawić, że potwierdzona rezerwacja zniknie z kalendarza.
Ważne jest też to, co klient zobaczy na ekranie: numer zgłoszenia, aktualny status i dalszy krok. „Wysłano formularz” nie zawsze znaczy „sala jest zarezerwowana”.
Najpierw trzeba nazwać reguły, potem zabezpieczyć ich przestrzeganie, a na końcu sprawdzić działanie w sytuacjach, które naprawdę występują w pracy.
Opowiedz, jak obsługujesz rezerwacje. Zaczniemy od zasad i problemów, które aplikacja ma rozwiązać.
Dokumentacja techniczna: przedziały i ograniczenia wykluczające PostgreSQL, rozszerzenie btree_gist.



