Кнопка обертається, вкладка показує помилку, а форма, яку ви заповнювали десять хвилин, зникла. Ви не знаєте, чи встиг запис пройти до обриву з'єднання. Саме ставлення до цієї невідомості як до провалу й створює дублікати коментарів, подвійні замовлення та повторні звернення до підтримки.

Відновлюйте в суворому порядку: збережіть текст, знайдіть результат і лише потім вирішуйте, чи допустиме друге відправлення.

Почніть із тексту та позначки часу

Скопіюйте вміст зі сторінки, перш ніж торкатися чогось іншого, включно з чернеткою, яку браузер ще тримає в полі. Запишіть час, сторінку, на якій ви були, і виконану дію, бо саме ці три деталі роблять можливим решту розслідування. Якщо вкладка ще відкрита, залиште її відкритою, доки не прочитаєте запис у мережі. Зберегти текст нічого не коштує, а втратити його — означає втратити все завдання.

Потім розділіть дві форми збою, які ви справді можете спостерігати. З'єднання, що обірвалося посеред запиту, і сервер, який відповів помилкою, виглядають у мережевій панелі по-різному, і лише друге говорить щось про рішення застосунку.

Шукайте результат у власному поданні застосунку

Перезавантажте подання для читання, яке показало б результат: список коментарів, історію замовлень, чергу звернень або запис, який ви редагували. Зіставляйте за обліковим записом, місцем призначення, часом і вмістом, а не за найсвіжішим записом, бо хтось інший міг написати після вас. Для фонового завдання шукайте наявне посилання та його стан, замість того щоб створювати нову операцію як перевірку зв'язку.

Якщо результат є, ви закінчили, і помилка стосується шляху відповіді, а не запису. Якщо його немає, залиште можливість, що застосунок ще не зафіксував його: завдання в черзі, затримане подання для читання або відстаюча репліка можуть деякий час приховувати успішний запис.

Перш ніж робити висновок, дайте цьому визначений другий погляд і запишіть час обох перевірок. Дві перевірки з інтервалом у двадцять секунд — значно слабший доказ, ніж дві з інтервалом у десять хвилин.

Вирішіть, чи безпечне друге відправлення

Відповідь залежить від операції, а не від вашого терпіння. HTTP відокремлює методи, які можна повторювати з тим самим задуманим ефектом, від тих, які не можна, і радить не повторювати автоматично другі, якщо не відомо, що семантика це дозволяє. Створення коментаря, оформлення замовлення й надсилання платежу зазвичай належать до другої групи, тому другий зовні успішний клік нічого не говорить про перший.

Якщо ви підтримуєте клієнт, використовуйте механізм повторних спроб або ідемпотентності, який документує API, і прив'язуйте його до тієї самої логічної операції, а не створюйте новий ключ для кожної спроби. Ідентифікатор запиту для трасування не є ключем придушення дублікатів, якщо сервер не ставиться до нього як до такого.

curl -i -X POST https://api.example.net/v1/orders \
  -H "Idempotency-Key: 6f1c2a94-3b7e-4a10-9c22-5d0e8f7b1a63" \
  -H "Content-Type: application/json" \
  --data @order.json

Ключ допомагає лише тоді, коли служба зберігає його разом з операцією і при повторі повертає початковий результат. Перевірте цю поведінку на тестовій кінцевій точці, перш ніж покладатися на неї у виробництві.

Зберіть докази, перш ніж знову щось натискати

Збережіть запис мережі, а не знімок екрана з помилкою. Метод запиту, URL, відповідь або тайм-аут і час, коли це сталося, — це те, що адміністратор може зіставити із записами застосунку. Експортуйте або скопіюйте запис як команду лише тоді, коли потім видалите з копії файли cookie, заголовки авторизації та будь-який приватний вміст. Залиште власну сесію недоторканою і ніколи не відтворюйте перехоплений запит з обліковими даними як короткий шлях.

Запитайте у власника сервісу одне конкретне питання: чи вдалася операція з цим вмістом у цей час і чи є на неї посилання? На це питання є відповідь, а на "чи зламався сайт" її немає.

Сенс вправи — встановити, що дія відбулася рівно один раз. Повідомлення про помилку, яке можна закрити, не те саме, що запис, якому можна довіряти, і саме друге потрібне вам, перш ніж надсилати будь-що інше.

Схожі статті