Как бороться с тем, что клиент не узнает о смене состояния сервера из-за таймаута?
Есть некоторое апи, которым пользуются мобильные клиенты.
Допустим у клиента плохая связь, он делает запрос к методу апи, сервер обрабатывает запрос и отдает ответ.
В этот момент у клиента испортилась связь и запрос завершается ошибкой по таймауту - он не узнает о смене состояния сервера (допустим делает что-то в случае успеха запроса).
Как решать проблему? Подтверждение получения клиентом?
При проектировании API необходимо предусмотреть, что бы все методы изменяющие состояние на сервере были безопасны для повторного вызова.
Делать это можно по сути 2мя способами, в зависимости от изменяемых данных и бизнес-логики.
1) При постинге комментариев можно например тупо проверять на сервере что последний комментарий от этого юзера не совпадает с новым.
2) Более универсально - делать все в 2 приема: первым запросом отправляем что нужно сделать, получаем в ответ некий id запроса. 2м запросом передаем этот id подтверждая что запрос нужно исполнить.
По поводу второго пункта, а если ответ от сервера с подтверждением подтверждения не придет из-за проблем с сетью но сервер работу выполнит...проблема остается той же, разве нет?
z0rgoyok: я имею ввиду что отправив подтверждение нужно также убедится что оно дошло до сервера, проблема повторяется но уже с запросом на подтверждение
Viktor Koltcov: Идея в том что каждый из запросов не ломает ничего сам по себе.
Т.е клиент отправляет подтвердение на сервер - допустим до сервера оно дошло и тут случился обрыв связи.
Клиент просто берет и отправляет это же подтверждение еще раз - сервер видит что такое уже было и говорит "ok".
На случай долгих разрывов можно дополнительно реализовать метод запроса статуса подтверждения, но это уже излишне как мне кажется
Дмитрий Энтелис: так вопрос в другом, допустим это курьерская доставка, курьер нажал "я доставлю", сервер об этом узнал или не узнал, курьер не может быть уверен, если случилась ошибка.
z0rgoyok: я так понимаю это резервирования заказа за курьером? кто первый успел тот и молодец?
Тогда все очень просто:
Шлем запрос на сервер "я доставлю этот заказ". Сервер обрабатывает запрос и отвечает статусом заказа в текущий момент (свободен, твой, не твой)
Если обрыв связи - просто шлем этот запрос еще раз, и так в цикле до тех пор пока таки не получим ответ от сервера.
Тут главное что бы сервер корректно обрабатывал такое поведение и спокойно отвечал каждый раз "чувак, заказ твой, все хорошо"
Дмитрий Энтелис: вопрос в том, как долго слать запрос "я доставлю"? курьер может просто отменить запрос через минуту, например, а сервер уже закрепил заказ за ним.
z0rgoyok: не должно быть у курьера возможности ничего отменить.
если запрос на сервер ушел - то пока мы не получили от сервера ответ с состоянием - все должно блокироваться.
Дмитрий Энтелис: да, но ведь возможна ситуация, что у него совсем пропала сеть/ выключился телефон, а доставлять надо прямо сейчас. в итоге заказ будет висеть на юзере без связи.
z0rgoyok: это вопрос бизнес логики уже а не клиент сервера.
Сделайте третий метод в апи "курьер получил уведомление что заказ доставлен ему".
Если отзыв не приходит в течении некоторого времени - шлите смс/звоните голосом, Etc
Ещё как вариант рассмотрите возможность асинхронного выполнения операций на сервере. Нужно организовать два-три метода в API. Первый метод запускает процесс изменения состояния (с валидацией текущего состояния и возможности его изменения) и не требует обязательного возврата результата. Второй метод (не обязательный) возвращает прогресс изменения состояния сервера. Третий - возвращает результат - текущее состояние сервера. В этом случае даже если на один из запросов не придёт ответа, клиент может запрос повторить.
Клиент генерирует UUID транзакции и отправляет ее на сервер.
Допустим она выполнялась долго и клиент схватил 500-ю. В этом случае клиент запрашивает (отдельный API метод) статус транзакции (UUID ее он знает). Если получает "все ок" - все ок)). Если ошибку: запрашивает отмену своей транзакции. Если 500-ю - пытается отменить транзакцию, выполняя запросы с экспоненциальной задержкой, пока не получит ответ: да, отменили мы твою транзакцию.