🌍 Вітаю! 🇧🇾
TL;DR
- TOCTOU — Time of Check to Time of Use, гонка между проверкой и использованием данных
- Реальный кейс: админ оценивал 2 кандидатов, за 50 секунд добавился 3-й → ошибка валидации
- Защита: Optimistic/Pessimistic locking, атомарные операции, UX-обновления страницы
🌍 Вітаю! 🇧🇾
На днях взял тикет, на работе, где пользователь 5 раз подряд прожимал отправку формы и 5 раз получил ошибку. Сидел 7 минут, ретраил, сильно пытался победить форму. 👨💻
Осторожно! ⚠️
Дальше скрытая реклама ☝️
Я открыл свой сервис для полуавтоматического исправления проблем, который за 10 минут разобрался и дал отчет с диагностикой, оказалось, это клаccический TOCTOU.
Меня это прям сильно заинтересовало. 😋
🔭 Что такое TOCTOU?
TOCTOU это
🍿 На пальцах: вы заметили что вкусный куличик все еще на своем месте 👌, пошли делать чаёк, вернулись — а ваша любимая семья уже сделала свое дело.
Как итог ваша проверка устарела.
В коде все аналогично: система проверяет состояние данных, а между проверкой и действием, данные меняются.
🪛 Реальный кейс
Есть форма, где нужно оценить ВСЕХ пользователей, которые находятся в определенном состоянии. Бизнеc логика простая: или оцениваем всех, или никого.
1️⃣ Пользователь открывает форму
➡️ Система подтягивает кандидатов в статусе "На оценке" — их 2
2️⃣ Пока администратор заполняет оценки (~5 минут), другой пользователь подвинулся в состояние на оценку.
➡️ В статусе "На оценке" теперь 3
3️⃣ Нажимает "Отправить"
➡️ Сервер: в запросе 2 кандидата, а в базе уже 3 → не совпадает → ошибка
🔖 Тайминги из базы
Ну чтоб не быть голословным, достал данные из логов:
➡️ 04:23 — пользователь B добавлен на оценку
➡️ ~04:25 — администратор открывает форму, видит кандидатов A и B
➡️ 04:31:32 — пользователь C создан
➡️ 04:31:46 — кандидат C попал в статус "На оценке"
➡️ 04:32:36 — отправка формы → ОШИБКА 💥
➡️ 04:33 — 04:39 — ещё 4 попытки, всё та же ошибка (форма все это время открыта с тем же составом пользователей)
50 секунд. Кандидат C залетел в нужный статус за 50 секунд до сабмита.
💡 Важный момент: проблемы из-за этого не произошло, валидация сработала ДО любых сайд-эффектов — ни один пользователь не был оценён частично, данные остались консистентными. Валидация свою работу сделала на 💯
🙌 Где ещё можно встретить TOCTOU?
Это не редкий фрукт, встречается постоянно:
➡️ Проверили наличие товара → пока оформляли заказ, последний купили
➡️ Проверили свободный слот → пока бронировали, кто-то занял
➡️ Проверили баланс → пока списывали, пришла другая транзакция
➡️ Проверили права на файл → пока открывали, файл подменили
Любая проверка, после которой идёт пауза до действия — потенциальный
🛡 Как защищаться?
➡️ Optimistic locking — version/timestamp на записи, при обновлении проверяем что версия не изменилась. Если изменилась — конфликт, повтор
➡️ Pessimistic locking — SELECT FOR UPDATE, блокируем запись на время операции. Надёжно, но медленнее
➡️ Атомарные операции — проверка и действие в одном запросе/транзакции, без зазора между ними
➡️ UX — показать пользователю, что данные изменились и предложить обновить форму
⚠️ В моём случае валидация была абсолютно правильной — она не давала оценить только часть кандидатов. Проблема была в UX: вместо понятного "появились новые кандидаты, обновите страницу" юзер получал непонятную ошибку и ретраил 7 минут 🤪
💬 Делитесь своим мнением в комментариях👇! Если вам понравился пост, не забудьте поставить лайк! 👍
#BUG
На днях взял тикет, на работе, где пользователь 5 раз подряд прожимал отправку формы и 5 раз получил ошибку. Сидел 7 минут, ретраил, сильно пытался победить форму. 👨💻
Осторожно! ⚠️
Дальше скрытая реклама ☝️
Я открыл свой сервис для полуавтоматического исправления проблем, который за 10 минут разобрался и дал отчет с диагностикой, оказалось, это клаccический TOCTOU.
Меня это прям сильно заинтересовало. 😋
🔭 Что такое TOCTOU?
TOCTOU это
Time of Check to Time of Use. Гонка между моментом проверки и моментом использования.🍿 На пальцах: вы заметили что вкусный куличик все еще на своем месте 👌, пошли делать чаёк, вернулись — а ваша любимая семья уже сделала свое дело.
Как итог ваша проверка устарела.
В коде все аналогично: система проверяет состояние данных, а между проверкой и действием, данные меняются.
🪛 Реальный кейс
Есть форма, где нужно оценить ВСЕХ пользователей, которые находятся в определенном состоянии. Бизнеc логика простая: или оцениваем всех, или никого.
1️⃣ Пользователь открывает форму
➡️ Система подтягивает кандидатов в статусе "На оценке" — их 2
2️⃣ Пока администратор заполняет оценки (~5 минут), другой пользователь подвинулся в состояние на оценку.
➡️ В статусе "На оценке" теперь 3
3️⃣ Нажимает "Отправить"
➡️ Сервер: в запросе 2 кандидата, а в базе уже 3 → не совпадает → ошибка
🔖 Тайминги из базы
Ну чтоб не быть голословным, достал данные из логов:
➡️ 04:23 — пользователь B добавлен на оценку
➡️ ~04:25 — администратор открывает форму, видит кандидатов A и B
➡️ 04:31:32 — пользователь C создан
➡️ 04:31:46 — кандидат C попал в статус "На оценке"
➡️ 04:32:36 — отправка формы → ОШИБКА 💥
➡️ 04:33 — 04:39 — ещё 4 попытки, всё та же ошибка (форма все это время открыта с тем же составом пользователей)
50 секунд. Кандидат C залетел в нужный статус за 50 секунд до сабмита.
💡 Важный момент: проблемы из-за этого не произошло, валидация сработала ДО любых сайд-эффектов — ни один пользователь не был оценён частично, данные остались консистентными. Валидация свою работу сделала на 💯
🙌 Где ещё можно встретить TOCTOU?
Это не редкий фрукт, встречается постоянно:
➡️ Проверили наличие товара → пока оформляли заказ, последний купили
➡️ Проверили свободный слот → пока бронировали, кто-то занял
➡️ Проверили баланс → пока списывали, пришла другая транзакция
➡️ Проверили права на файл → пока открывали, файл подменили
Любая проверка, после которой идёт пауза до действия — потенциальный
TOCTOU🛡 Как защищаться?
➡️ Optimistic locking — version/timestamp на записи, при обновлении проверяем что версия не изменилась. Если изменилась — конфликт, повтор
➡️ Pessimistic locking — SELECT FOR UPDATE, блокируем запись на время операции. Надёжно, но медленнее
➡️ Атомарные операции — проверка и действие в одном запросе/транзакции, без зазора между ними
➡️ UX — показать пользователю, что данные изменились и предложить обновить форму
⚠️ В моём случае валидация была абсолютно правильной — она не давала оценить только часть кандидатов. Проблема была в UX: вместо понятного "появились новые кандидаты, обновите страницу" юзер получал непонятную ошибку и ретраил 7 минут 🤪
💬 Делитесь своим мнением в комментариях👇! Если вам понравился пост, не забудьте поставить лайк! 👍
#BUG

Хотите больше таких постов?
Подпишитесь на канал и читайте продолжение в Telegram.