Якщо одна помилка повинна провалити групову операцію?


11

В API, над яким я працюю, є операція масового видалення, яка приймає масив ідентифікаторів:

["1000", ..., "2000"]

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

try{
savepoint = conn.setSavepoint();

for(id : IDs)
    if( !deleteItem(id) ){
        conn.rollback(savepoint);
        sendHttp400AndBeDoneWithIt();
        return;
    }

conn.commit();
}

Альтернатива (впроваджена в іншому місці нашого програмного пакету) полягає в тому, щоб зробити все, що ми можемо, в сервісному періоді та повідомити про помилки в масиві. Ця частина програмного забезпечення стосується меншої кількості запитів, тому відповідь не закінчується гігантським масивом ... теоретично.


Нещодавня помилка, що виникає на сервері з обмеженими ресурсами, змусила мене знову переглянути код, і тепер я ставлю під сумнів своє первісне рішення - але цього разу мене більше мотивують потреби бізнесу, а не найкраща практика. Якщо, наприклад, я не проважую весь запит, користувачеві доведеться спробувати ще раз, тоді як якщо кількість елементів буде видалено, користувач може закінчити дію, а потім попросити адміністратора зробити все інше (поки я працюю над виправленням помилки !). Це був би дозвільний режим.

Я спробував шукати в Інтернеті деякі поради з цього питання, але я прийшов з порожніми руками. Тож я приходжу до вас: Чого найбільше очікують масові операції такого характеру? Чи варто дотримуватися суворішого, чи мені бути більш дозволеною?


9
Це залежить. Яка вартість того, щоб щось не видалено, коли воно має бути? (Вартість визначається як погані дані, головний біль, небажана поведінка, час, який потрібно адміністратору, щоб виправити це і т.д.) Чи прийнятно це? Якщо ти зможеш жити з наслідками того, що не вийде з ладу все, піди на це. Якщо це спричинить занадто багато проблем, не робіть цього. Ви знаєте своє програмне забезпечення та наслідки, тому вам доведеться зателефонувати.
Becuzz

1
@Becuzz Вартість, що користувач помітить один-два залишки та відкриє квиток про це; поточна ситуація "Omg delete порушено". На щастя, користувач знаходиться в передпокої, тому цього разу це не надто багато проблем. Справа в тому, що мені подобається робити правильну справу, коли це можливо, і з кодовою базою 10 років, Бог знає, що деякі речі можуть бути зроблені правильно
rath

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

1
@ imnota4 Чудовим моментом я не вважав. Користувальницький інтерфейс обмежує запит максимум приблизно на 250, але бекенд не має обмежень. Можу попросити перевмістити коментар як відповідь?
рат

1
Дозвільний режим також полегшує роботу адміністраторів, оскільки їм не потрібно відтворювати помилку з усім стеком ідентифікаторів. Також може бути корисно повідомити у відповідь причину кожної помилки. Дивлячись на причину, для кінцевого користувача це може бути вирішено без квитків "OMG delete не порушено".
Лаїв

Відповіді:


9

Добре робити «сувору» або «приємну» версію кінцевої точки видалення, але потрібно чітко повідомити користувачеві, що сталося.

Ми робимо дію видалення з цією кінцевою точкою. Ймовірно, DELETE /resource/bulk/чи щось подібне. Я не прискіпливий. Тут важливо те, що незалежно від того, чи вирішили ви бути суворими чи приємними, вам потрібно повідомити про те, що саме сталося.

Наприклад, API, з яким я працював, мав DELETE /v1/student/кінцеву точку, яка приймала масові ідентифікатори. Ми регулярно надсилаємо запит під час тестування, отримуємо 200відповідь і припускаємо, що все нормально, лише щоб пізніше з’ясувати, що всі в списку все ще були в базі даних IN (встановлені на неактивний) або насправді не видалялися через помилку, яка переплутали майбутні дзвінки, GET /v1/studentтому що ми отримали назад дані, яких ми не очікували.

Вирішення цього питання з’явилося в пізнішому оновлення, яке додало тіло до відповіді з ідентифікаторами, які не були видалені. Це - наскільки мені відомо - свого роду найкраща практика.

Підсумок, незалежно від того, що ви робите, переконайтеся, що ви надаєте спосіб інформувати кінцевого користувача про те, що відбувається, і, можливо, чому це відбувається. IE, якби ми вибрали суворий формат, відповідь могла бути 400 - DELETE failed on ID 1221 not found. Якби ми вибрали "приємну" версію, це могло б бути 207 - {message:"failed, some ids not deleted", failedids:{1221, 23432, 1224}}(вибачте за моє погане форматування json).

Удачі!


6
207 Multi-Statusможе бути доречним для часткової реакції на відмову
Річард Тінгл

1
ТАМ МИ ЙДЕМО! Я насправді цього не міг згадати! Я буду продовжувати і оновити відповідь на це, оскільки це насправді відповідає стандарту.
Адам Уеллс

2

Слід бути суворим і вседозволеним.

Зазвичай насипні навантаження розбиваються на 2 фази:

  • Перевірка
  • Завантаження

Під час фази перевірки кожен запис розглядається суворо, щоб переконатися, що він відповідає вимогам специфікацій даних. За кілька секунд можна легко перевірити 10 з 1000 записів. Дійсні записи розміщуються в новому завантажуваному файлі, недійсні (і) позначені і видаляються і зазвичай містяться в окремому файлі (пропускний файл). Потім повідомлення надсилається на запис (и), що не вдалося перевірити, щоб їх можна було перевірити та діагностувати з метою усунення несправностей.

Після перевірки даних вони завантажуються. Зазвичай він завантажується партіями, якщо він досить великий, щоб уникнути тривалих операцій або якщо стався збій, відновити його буде простіше. Розмір партії залежить від того, наскільки великий набір даних. Якщо в одному лише декілька 1000 записів, одна партія буде в порядку. Тут ви можете бути дещо дозволеними з відмовами, але, можливо, потрібно встановити невдалий поріг партії, щоб зупинити всю операцію. Можливо, якщо [N] пакетів не вдасться, один призупинив би всю операцію (якщо сервер не працює або щось подібне). Зазвичай, у цій точці немає збоїв, оскільки дані вже перевірені, але якщо вони виникли через проблеми із оточенням чи інші, просто перезавантажте пакет, що не вдався. Це трохи полегшує одужання.


Я не перевіряю ідентифікатори щодо значень БД, я просто намагаюся їх видалити і побачити, як це відбувається, або це займе назавжди. Аборт після N невдач здається дуже розумною пропозицією, +1
рат

2

Якщо одна помилка повинна провалити групову операцію?

Канонічної відповіді на це немає. Необхідно вивчити потреби та наслідки для користувача та оцінити компроміси. ОП дав деяку необхідну інформацію, але ось як би я діяв:

Запитання 1 : "Який наслідок для користувача, якщо окреме видалення не вдається?"

Відповідь повинна керувати рештою дизайнерської / реалізованої поведінки.

Якщо, як заявлено в ОП, користувач просто помічає виняток і відкриває проблемний квиток, але в іншому випадку це не впливає (видалені елементи не впливають на наступні завдання), я б пішов з дозволом з автоматичним сповіщенням тобі.

Якщо невдалі делети повинні бути вирішені до того, як користувач може продовжити, то чіткі переваги явно краще.

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

Питання 2 : "Чи можуть виникнути проблеми з узгодженістю / узгодженістю даних, якщо наступні завдання виконуються з не видаленими елементами, які все ще зберігаються в сховищі даних?"

Знову ж таки, відповідь призведе до найкращого дизайну / поведінки. Так -> Строгий, Ні -> Дозволений, Можливо -> Строгий або вибраний користувачем (особливо, якщо від користувача можна залежати, щоб точно визначити наслідки).


0

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


-1

Я б сказав, що тут важливим моментом є те, що означає видалити більшу частину речей.

Чи ці ідентичні дані якось логічно пов'язані, чи це просто зручність / продуктивність - групове групування цих?

У випадку, якщо якимось чином, навіть нещільно пов'язаним, я б пішов strict. Якщо це просто пакетний режим (наприклад, користувач натискає "зберегти" протягом останніх хвилин роботи, і лише тоді пакет передається), то я б пішов на permissiveверсію.

Як і в іншій відповіді: У будь-якому випадку повідомте «користувачеві», що саме сталося.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.