Как реализовать удаление нескольких элементов при ограничении бэкенда на один запрос на удаление
Что проверяют
Умеете ли вы превратить одно действие пользователя в N сетевых запросов и не потерять консистентность: что показать на экране, сколько запросов слать одновременно и что делать, если часть из них упала. Следом спрашивают про частичный успех и про уход приложения в фон посреди операции.
Как отвечать
Каркас из четырёх шагов:
- оптимистичный интерфейс: сразу убираете выбранные ячейки через diffable data source, но держите их идентификаторы в состоянии «удаляется», чтобы вернуть при ошибке;
- ограниченная параллельность:
withThrowingTaskGroupилиwithTaskGroup, в которую сначала кладёте несколько задач, скажем четыре, а новую добавляете после каждогоgroup.next(). Сотня одновременных запросов упрётся в лимиты сервера, а поочерёдная отправка медленная; - результат по каждому элементу: собираете успехи и ошибки отдельно, удачные удаляете окончательно из локального хранилища, неудачные возвращаете в список и показываете «Удалено 8 из 10, повторить?»;
- повторы:
DELETEидемпотентен, поэтому при таймауте его можно повторить, а ответ 404 на повторе считать успехом. На 429 уважайтеRetry-Afterи повторяйте с экспоненциальной паузой.
Если удаление должно пережить закрытие приложения, очередь идентификаторов сохраняют в SwiftData или Core Data и досылают при следующем запуске. Фоновая URLSession тут не поможет: она поддерживает только задачи скачивания и отправки файлов, а для короткого добора времени есть beginBackgroundTask.
Обязательно скажите, что правильное решение на уровне продукта это пакетный эндпоинт на бэкенде, а клиентская очередь лишь обход ограничения.
Где спотыкаются
Запускают все запросы через DispatchGroup без ограничения и в конце вызывают completion(true) независимо от результатов. Пользователь видит успех, а половина элементов осталась на сервере.
Мутируют общий массив из параллельных замыканий и получают гонку данных. В языковом режиме Swift 6 компилятор такое обычно не пропускает, решение через актор или сбор результатов из группы.
Хранят очередь в UserDefaults и пишут туда на каждое изменение. Он предназначен для настроек, а не для данных, которые должны пережить сбой.