Как реализовать уникальные идентификаторы заказов для предотвращения дублирования?
Что проверяют
Понимаете ли вы, откуда берутся дубли заказов: двойной клик, повтор после таймаута, две вкладки, ретрай в сетевом слое. И что генерация ID сама по себе от них не спасает, спасает идемпотентность. Следом спрашивают, кто в этой схеме отвечает за уникальность, фронтенд или сервер.
Как отвечать
Правильный ответ строится вокруг ключа идемпотентности:
- когда генерировать: один раз при открытии оформления или создании черновика заказа, а не на каждый клик. Храните его в состоянии формы и в
sessionStorage, чтобы он пережил перезагрузку страницы; - чем генерировать:
crypto.randomUUID(). Он криптостойкий, есть во всех актуальных браузерах, но работает только в безопасном контексте, то есть по HTTPS или на localhost; - как передавать: в заголовке
Idempotency-Keyили полем запроса. Любой повтор того же оформления идёт с тем же ключом; - что делает сервер: хранит ключ под уникальным ограничением. Повтор с тем же ключом получает сохранённый ответ первого запроса, тот же ключ с другой корзиной получает ошибку (обычно 422), а повтор, пока первый ещё обрабатывается, получает 409;
- когда менять ключ: после успешного заказа или когда пользователь изменил корзину и оформляет заново.
На интерфейсе добавьте блокировку кнопки на время запроса и состояние «Оформляем». Но это удобство, а не защита: повтор после таймаута кнопка не отловит.
Если спросят про формат ID в базе, упомяните UUIDv7 из RFC 9562: он упорядочен по времени и меньше фрагментирует B-tree индекс, чем случайный v4. Номер заказа для людей обычно отдельное короткое поле.
Где спотыкаются
Генерируют UUID через Math.random() по старому шаблону из интернета. Это не криптостойкий генератор: значения теоретически предсказуемы, а гарантий уникальности нет никаких.
Предлагают AUTO_INCREMENT как защиту от дублей. Автоинкремент выдаст второму запросу новый номер, и дубль спокойно сохранится, плюс по номерам видно, сколько у вас заказов.
Считают, что проверки на фронтенде достаточно. Клиенту нельзя доверять: запрос можно повторить из DevTools или скриптом, поэтому уникальность обеспечивает только ограничение в базе.