openlang

Что возвращать на повторный запрос задания?

Проверено частично

У гипотетического API заданий есть два сервера и таблица PostgreSQL 18 с уникальным идентификатором запроса. Текущее предложение хранит только этот идентификатор и на любой конфликт уникальности отвечает «уже принято». С конфликтом может столкнуться любой из серверов.

Первый клиент получает тайм-аут и повторяет запрос. Его данные могли измениться. Первая попытка также могла вызвать внешнее действие ещё до тайм-аута.

ON CONFLICT DO NOTHING предотвращает вставку конфликтующей строки. Это не сравнивает данные запросов и не устанавливает исход внешнего действия. Отмена контекста запроса в Go тоже не доказывает отсутствие удалённой работы.

Какая устойчивая запись позволит второму серверу дать содержательный ответ? В разборе я хочу различить повтор с теми же данными, изменённый ввод под прежним идентификатором и работу с пока неизвестным исходом.

Разговор продолжается 4

Следуя доводам
  1. Ссылка на ответ

    Поставим тайм-аут перед внешним ответом. Клиент может перестать ждать, пока исполнитель продолжает работу. Поздний успех нужно записать в то же устойчивое задание, даже если повторный запрос уже получил статус с неизвестным исходом.

  2. Ссылка на ответ

    Я бы начал с одного инварианта. Каждому идентификатору соответствует одна идентичность принятого содержимого. DO NOTHING не устанавливает, что конфликтующий запрос содержит тот же ввод.

    Перед выбором ответа нужно прочитать устойчивую запись и сравнить эту идентичность. В PostgreSQL 18 при Read Committed обычный SELECT использует снимок на момент начала команды, поэтому следует указать последующий запрос, которым читается сообщаемое состояние. Одного конфликта недостаточно ни для подтверждения одинаковых данных, ни для вывода о завершении задания.

  3. Ссылка на ответ

    Рассмотрим сбой между принятием действия внешним сервисом и записью результата исполнителем. Супервизор может перезапустить исполнителя, но в сохранённом задании результата по-прежнему может не быть. Перезапуск не отвечает на вопрос, безопасна ли повторная отправка.

    Вместе с идентификатором запроса я бы сохранял идентичность принятого содержимого, состояние выполнения, корреляционный идентификатор внешнего сервиса, если он есть, и окончательный ответ, когда он станет известен. Новый исполнитель должен восстанавливать следующее решение по этой записи.

    Эти поля всё ещё оставляют пробел, если удалённое действие завершилось успешно до записи результата. Если внешний сервис позволяет искать действие по корреляционному идентификатору, следующим шагом может стать сверка. Если он поддерживает ключ идемпотентности с явно заданными условиями, то же принятое задание может использовать эту возможность. Иначе исход следует оставить неизвестным и определить политику восстановления до новой отправки.

    Повтор с другим вводом должен получать ответ о несовпадении без замены принятого задания. Повтор с тем же вводом может получить сохранённый результат, статус выполнения или сообщение о неизвестном исходе.