Skip to main content

ETag и оптимистическая блокировка

Версия объекта — W/"<DataVersion>".
  • Сущность по ключу и ответы записи несут заголовок ETag.
  • Каждая сущность в выдаче несёт @odata.etag, если выбран DataVersion.
У записей регистров и констант версии нет, для них подходит только If-Match: *. Флажок «Требовать If-Match» на вкладке «Запись» (по умолчанию выключен) делает заголовки обязательными. PATCH, PUT, DELETE, Post и Unpost без If-Match получают 428, а POST без If-None-Match: * — тоже 428.

Повторяемые запросы

Сеть может оборвать ответ после того, как объект уже записан. Чтобы повтор не создал дубль, передайте один из заголовков:
  • Repeatability-Request-ID (OData 4.01). Учитываются также Repeatability-Client-ID и Repeatability-First-Sent;
  • Idempotency-Key.
Как это работает:
  • Запрос выполняется в одной транзакции с сохранением ответа. Ключ — субъект и хеш заголовка с его значением.
  • Повтор с тем же ключом от того же субъекта ждёт окончания первого запроса и получает сохранённый ответ (статус, заголовки, тело). Повторно запрос не выполняется.
  • Тот же ключ с другим методом, адресом или телом — 422.
  • Repeatability-First-Sent старше срока хранения — 400.
  • С Repeatability-Request-ID ответ несёт Repeatability-Result: accepted, у отказов — rejected.
  • Ответы с ошибкой не хранятся: запись откатилась, и повтор выполняется заново.
  • Срок хранения задаёт поле «Срок хранения повторов, часов» на вкладке «Запись» (по умолчанию 24). Старые записи удаляет регламентное задание «Очистка OData4».
  • В $batch заголовок действует для отдельных операций (он ставится в операции), но не для пакета целиком.
Ответ записи, в том числе с $expand, собирается до фиксации транзакции. Если сборка ответа сорвалась, откатывается и запись, поэтому 500 после уже записанного объекта из-за ответа не бывает.

Ключ нового объекта

Ref_Key в теле POST задаёт ссылку нового объекта. Занятость ключа проверяется в транзакции записи среди всех объектов, включая скрытые профилем и RLS. Параллельные POST с одним ключом дают один 201 и один 409, дубля нет. Ответ 409 на ключ скрытого объекта раскрыл бы, что объект существует. Поэтому субъекту, у которого для набора есть отборы строк профиля, Ref_Key по умолчанию запрещён: ответ 400 «Свойство Ref_Key: ключ нового объекта задаёт сервис…». Настройка «Ключ при создании» = «Разрешён» снимает запрет. Тогда 409 одинаков для видимого и скрытого объекта, а существование скрытого объекта по известному GUID можно узнать.

Проверка ссылок тела

Каждая непустая ссылка в теле записи должна вести на существующий объект, который субъект видит при чтении. Это касается ссылок на справочник, документ, план, узел обмена, бизнес-процесс или задачу в реквизите, …@odata.bind, составном поле, строке табличной части и строке набора движений. Видимость определяют набор модели профиля, его отборы строк и RLS. Если ссылка не проходит проверку, ответ — 400 «Свойство X: объект не найден или недоступен». У строки табличной части свойство указывается как ТЧ[N]/X, у набора движений — RecordSet[N]/X. Текст одинаков для «нет» и «не видно».
  • Значение, которое уже было у объекта в этом поле, не проверяется. Объект со ссылкой на скрытое можно менять, не трогая её.
  • Объекты видов вне состава публикации проверяются только на существование и RLS.
Режим выбирается в настройке «Проверка ссылок записи»:

Как безопасно повторять запрос

Если ответ потерян или пришёл 500, объект мог быть уже записан. Повторяйте так:
Передавайте Repeatability-Request-ID или Idempotency-Key. Повтор получит сохранённый ответ без повторного выполнения.
Задайте свой Ref_Key и If-None-Match: *. Повтор получит 412 или 409, объект останется один. Субъекту с отборами строк профиля Ref_Key по умолчанию закрыт (см. выше).
Повторяйте с If-Match. Если запись прошла, версия уже другая, и повтор получит 412.
Прочитайте объект и проверьте результат: пометку удаления или признак Posted.
Изредка при включённом журнале запросов платформа отвечает 500 «Тип не определен ’…’» на первый запрос после простоя сеанса. Запрос записи к этому моменту уже зафиксирован, поэтому повторяйте его одним из способов выше. Подробнее — на странице Известные ограничения.