Files
huncode 6c4f980f51
Build and deploy / deploy (push) Successful in 14s
revise June 2020 idempotency articles
2026-07-31 11:32:33 +03:00

13 KiB
Raw Permalink Blame History

Июнь 2020 — тройное ревью автономного пакета P28 «Повторы запросов и идемпотентность»

Статус: принят в publication registry 31 июля 2026 года. Ревизии накладываются по стабильным slug, сохраняют дату и автора базового архива и не перезаписывают articles.json.

Проверенные revision:

  • editorial-2020-06-practice-retry-idempotency;
  • editorial-2020-06-mechanism-retry-idempotency;
  • editorial-2020-06-field-retry-idempotency.

Модуль экспортирует ровно три revision. В объектах нет date и author, поэтому будущий publication layer должен сохранить стабильные дату и автора из базового архива. При запуске --print-revisions stdout содержит только JSON; отдельная --verify-fixture печатает результат учебной in-memory проверки.

Проход 1. Факты, механизм и ограничения — пройдено

Утверждение или решение Первичный / официальный источник Проверенная граница
HTTP различает идемпотентные методы и POST; 409, 503 и Retry-After не создают idempotency сами по себе RFC 7231 Статьи не называют любой POST безопасным для автоповтора и не приписывают одному status универсальную retry-policy.
Идея key, fingerprint, replay завершённой операции и конфликта параллельного повтора уже была описана в начале 2020 года draft-idempotency-header-01 Документ назван историческим work in progress, не готовым стандартом и не причиной считать header универсально поддержанным.
Timeout клиентского HTTP-request не отменяет серверный business effect автоматически Node.js v12: ClientRequest.setTimeout Все timeout в статьях описаны как неизвестный исход для наблюдающей стороны, а не как rollback.
Уникальный scope и атомарный захват записи должны жить в устойчивом хранилище PostgreSQL 12: Constraints, INSERT / ON CONFLICT Учебная SQL-схема не выдаёт процессную память за защиту от двух процессов и отделяет внутреннюю транзакцию от внешнего effect.

Технический разбор проверен повторно после редакторских правок:

  • key имеет scope actor + operation + key, а fingerprint отделяет retry того же payload от другой команды;
  • completed хранит минимальный terminal response для replay; in_progress и mismatch payload останавливают второй handler до business effect;
  • для эффекта внутри одной базы учебный пример сохраняет объект и terminal запись в одной транзакции;
  • для внешнего вызова текст прямо требует отдельный устойчивый key либо status route и не обещает exactly once локальной таблицей;
  • retention key должен быть длиннее документированного retry-budget. Удаление in_progress не показано как средство исправить сбой.

Выполнена автономная фикстура --verify-fixture. Реальный вывод подтверждает: первая доставка имеет response_lost, создан ровно один effect, retry возвращает сохранённый demo-request-42, а тот же key с другой hash получает 409. Фикстура не открывает сеть, базу, proxy или внешний API.

Все адреса, ключи, payload, result ID, журналы и тайминги учебные: api.training.invalid, 127.0.0.1:48080, demo-key-retry-2020-06-a7f1 и demo-request-42. Нет реальных платёжных данных, credentials, endpoint или утверждения о production инциденте.

Вердикт прохода: пройден. Исторические источники и пример согласованы; механика ограничена тем, что пакет действительно проверяет.

Проход 2. Редактура, голос М3 и объём — пройдено

Revision Проблема и цена в первых двух абзацах Главный вопрос Голос и следующее действие
Практика Потерянный ответ приводит к двойной заявке и ручной чистке Как удержать один intent, key и конечный retry-budget на стороне клиента М3 связывает UI с API-contract; маршрут вводит key до первой попытки и проверяет «response lost → replay».
Механизм Два POST конкурируют, а boolean не объясняет состояние результата Как сохранить scope, fingerprint и terminal response в устойчивом хранилище М3 связывает HTTP с SQL-границей, но не выдаёт локальную таблицу за глобальную exactly-once гарантию.
Полевой разбор Один timeout скрывает три разных пути и провоцирует blind retry Как собрать requestId, key, журнал и временной budget в одну проверку М3 связывает frontend, edge и backend через учебную трассу без современного observability stack.
  • Draft gate после финальной правки измерил основной текст без источников: практика — 10 899 знаков, механизм — 11 577, полевой разбор — 11 331. Все три текста лежат в диапазоне 5 000–15 000 знаков.
  • В каждом материале проблема и цена названы в первых двух абзацах. Затем сохранена короткая последовательность «симптом → причина → проверка → действие», а не общая речь о надёжности.
  • У каждой revision есть не менее пяти смысловых разделов, таблица с caption/thead, figure с осмысленными alt/figcaption, HTTP/code/log example, нумерованный маршрут и минимум две первичные или официальные ссылки.
  • Удалены поздние для автора 2020 года обобщения: нет payment API как основы примера, event streaming, SLO, распределённой трассировки или фальшивого опыта крупного production-инцидента. Внешний effect, proxy и база названы границами, которые ещё нужно проверить в конкретном проекте.

Вердикт прохода: пройден. Тексты плотные, прагматичные и соответствуют М3 / июню 2020 года.

Проход 3. Визуал и выпуск автономного пакета — пройдено в заданных границах

  • retry-idempotency-request-path-2020.svg показывает один intent, первую доставку, потерянный ответ и replay. Он объясняет, почему timeout не создаёт право послать новый key.
  • retry-idempotency-state-contract-2020.svg показывает scope, атомарный захват записи, ветки completed/conflict и отдельную границу внешнего effect.
  • retry-idempotency-diagnosis-2020.svg показывает разные requestId попыток и общий idempotency key на временной шкале.
  • У SVG есть title, desc, role="img", вертикальные viewBox, контрастные карточки и короткие подписи. Нет JavaScript, foreignObject, внешних URL или растровых data URI.
  • Диаграммы отрендерены через Sharp при ширине 375 px. Независимый визуальный проход обнаружил слишком длинные нижние подписи во второй и третьей схеме; подписи сокращены и разбиты на строки. Финальные 375 px PNG прочитаны повторно: обрезания, наложения и горизонтальный overflow внутри SVG не обнаружены.
  • Основной редактор отдельно просмотрел финальные raster-версии на 375 px и подтвердил вывод. После подключения registry strict audit и production build пройдены; они не подменяют реальный HTTP, PostgreSQL или внешний effect.

Фактические команды и результаты

cd web
node --check scripts/upgrade-2020-06.mjs
npm run audit:draft -- scripts/upgrade-2020-06.mjs
node scripts/upgrade-2020-06.mjs --verify-fixture
xmllint --noout \
  public/assets/editorial/2020/retry-idempotency-request-path-2020.svg \
  public/assets/editorial/2020/retry-idempotency-state-contract-2020.svg \
  public/assets/editorial/2020/retry-idempotency-diagnosis-2020.svg
Проверка Реальный результат
node --check код завершения 0
Draft audit PASS: 10 899 / 11 577 / 11 331 знаков тела
In-memory fixture effects = 1; четыре логические проверки вернули true
XML все три SVG валидны, код завершения 0
375 px visual preflight выполнен после финальной правки; читаемость и границы подтверждены локальным Sharp-рендером
Strict audit после подключения registry PASS: 10 899 / 11 577 / 11 331 знаков; 2 / 2 / 2 table и 3 / 2 / 3 code example
npm run build PASS, code 0, 374 статические страницы
Scope/self-review PASS: в revision нет date/author, articles.json не перезаписан

Не запускались browser-review опубликенной страницы, proxy, PostgreSQL, curl-команды, интеграционный стенд или production deployment. Учебный маршрут не выдан за опубликованную HTTP-функциональность. Проверка assistive technology также не заявляется; у рисунков есть структурные alt-тексты и подписи, но это не заменяет реальную проверку скринридером.

Итог

Статус: тройное ревью пройдено, пакет принят к публикации.

Изменения после трёх проходов:

  1. SQL-псевдокод механизма приведён к тексту: внутренний effect и terminal idempotency record показаны внутри одной учебной транзакции.
  2. Две длинные мобильные подписи SVG сокращены и разбиты так, чтобы сохранить крупный шрифт в 375 px.
  3. Registry заменяет только редакционные поля по стабильному slug; архив, standard, очередь и package configuration не перезаписаны.