Как решается задача слияния корзин анонимного и авторизованного пользователя
Что проверяют
Умеете ли вы продумать бизнес-правила и граничные случаи, а не только «сложить два списка». Следом обычно спрашивают, что будет, если пользователь вошёл почти одновременно в двух вкладках, и что делать с товаром, который закончился.
Как отвечать
Сначала хранение гостевой корзины. Её идентифицируют по cartId (UUID) в cookie или по гостевому токену у мобильного клиента, а саму корзину держат в таблице с nullable user_id или в Redis с TTL. Привязывать её к id HTTP-сессии опасно: Spring Security при входе по умолчанию меняет id сессии (changeSessionId) для защиты от session fixation, и внешний ключ по старому id потеряется.
Точка слияния: успешная аутентификация. В Spring это AuthenticationSuccessHandler или слушатель AuthenticationSuccessEvent, у мобильного клиента явный вызов слияния после получения токена.
Правила слияния стоит назвать явно:
- ключ позиции: SKU, то есть товар вместе с размером и цветом, а не id товара;
- совпадение позиций: количество складывают или берут максимум, в любом случае с потолком по остатку и лимиту на заказ;
- цены и промокоды: пересчитываются по актуальным правилам, гостевая цена не переносится;
- недоступные товары: не удаляются молча, а помечаются, чтобы интерфейс мог сказать «часть товаров закончилась»;
- идемпотентность: слияние идёт в одной транзакции, корзину пользователя блокируют (
SELECT ... FOR UPDATEили@Versionдля оптимистической блокировки), а гостевую не удаляют, а переводят в статусMERGED. Повторный вызов из второй вкладки ничего не сделает.
Упомяните и альтернативы: заменить корзину пользователя гостевой или спросить его самого. Выбор за продуктом, ваша задача назвать варианты.
Где спотыкаются
Убирают «дубли» по id товара и теряют разные размеры одной модели. Или складывают количества без проверки остатка.
Не думают о гонке. Два входа почти одновременно дают двойное слияние и удвоенное количество, если операция не идемпотентна.
Не сбрасывают cookie гостевой корзины после слияния. После выхода и нового входа та же корзина сольётся повторно, и количества снова удвоятся.