# Автономное тройное ревью П38 · апрель 2021 · «Согласованность данных между сервисами»
Статус: **авторское тройное ревью пройдено, затем пакет принят независимым
редактором в выпусковой набор**. Пакет содержит три revision для стабильных
slug:
- editorial-2021-04-practice-data-consistency;
- editorial-2021-04-mechanism-data-consistency;
- editorial-2021-04-field-data-consistency.
Созданы только пять разрешённых файлов:
1. web/scripts/upgrade-2021-04.mjs;
2. editorial/reviews/2021-04-draft.md;
3. web/public/assets/editorial/2021/data-consistency-state-machine-2021.svg;
4. web/public/assets/editorial/2021/data-consistency-compensation-2021.svg;
5. web/public/assets/editorial/2021/data-consistency-diagnosis-2021.svg.
Revision-модуль экспортирует только изменяемые редакционные поля. В нём нет
date, author или подключения registry.
articles.json, README, очередь, стандарты, package config и Git
не менялись. Команды --print-revisions и
--verify-fixture предназначены только для import-safe проверки
этого пакета.
## Проход 1. Факты, историческая рамка и техника — пройдено
| Утверждение | Первичный или официальный источник | Проверенная граница |
| --- | --- | --- |
| Контекст события может включать id, source и type; version 1.0.1 CloudEvents уже существовала к апрелю 2021 года | [CloudEvents Specification v1.0.1: release record](https://github.com/cloudevents/spec/releases/tag/ce%40v1.0.1) | Учебный конверт заимствует только понятные поля. Он не является полной реализацией CloudEvents, transport binding или broker API. |
| PostgreSQL 13 документирует локальную transaction isolation, serialization failure и необходимость retry в соответствующих случаях | [PostgreSQL 13: Transaction Isolation](https://www.postgresql.org/docs/13/transaction-iso.html) | Это граница одной базы owner-а. Она не делает атомарными две базы, event delivery и внешний reserve API. |
| INSERT ... ON CONFLICT задаёт альтернативу для unique/exclusion constraint в одном PostgreSQL-хранилище | [PostgreSQL 13: INSERT](https://www.postgresql.org/docs/13/sql-insert.html) | compensation_key примера защищает повтор локального решения, а не доказывает cross-service consistency. |
| Kafka 2.7 отделяет producer idempotence и ограничивает её одной session, отдельно предупреждая о application-level resend | [KafkaProducer 2.7.0 API](https://kafka.apache.org/27/javadoc/org/apache/kafka/clients/producer/KafkaProducer.html) | Set event id fixture подавляет один duplicate event только в памяти; статьи не обещают exactly-once business effect. |
Технический сценарий намеренно ограничен одним учебным object id
order-417. Owner сначала находится в paid v2.
Проверенный учебный reason training-reservation-rejected даёт
owner-у право создать cancelled v3 с единственным
compensationKey. Consumer получает v3 раньше v2, сохраняет
version gap, применяет v2 и затем replay-ит отложенную v3. Повтор v2/v3 не
создаёт новый state transition.
Инварианты fixture:
- owner не создаёт вторую компенсацию для того же compensationKey;
- consumer не меняет projection при gap и не двигает version назад;
- duplicate event id не создаёт второй state transition;
- cancelled v3 не разрешает следующий эффект
readyToShip.
Fixture использует только Array, Map и Set одного Node-процесса. Она не
запускает database, broker, HTTP service, external reserve, real order,
transaction manager или distributed delivery. Компенсирующее действие в
статьях описано как паттерн решения owner-а, не как единый стандарт или
готовая platform capability.
Вердикт прохода: **пройден**. Источники существовали к апрелю 2021 года, а
проверенные факты не расширены до обещания общей транзакции, готового
distributed workflow или exactly-once business effect.
## Проход 2. Редактура, глубина и голос М4 — пройдено
Final draft audit подтвердил объём 5–15 тыс. знаков. Тексты держат короткую
прагматичную речь
«симптом → причина → проверка → действие» и М4 апреля 2021 года: ownership,
инвариант, evidence и ограниченная компетентность вместо claims о
распределённой платформе.
| Revision | Симптом и цена в первых двух абзацах | Главный вопрос | Итоговый объём |
| --- | --- | --- | --- |
| Практика | owner и fulfillment показывают разные versions; цена — совершить отгрузку или другой effect по отставшей проекции | Как назвать owner, инвариант следующего действия и границу eventual consistency | **10 294** знака body |
| Механизм | v3 приходит до v2 и duplicate повторяется; цена — перепрыгнуть переход, откатить projection назад или создать вторую компенсацию | Почему event id, version и compensation key нельзя заменить одним идентификатором | **10 790** знаков body |
| Полевой разбор | статусы расходятся, оператору хочется переписать их вручную; цена — потерять evidence и получить второй effect | Как собрать evidence packet и выбрать безопасное действие до replay | **11 728** знаков body |
Редакторский проход подтвердил:
- table с caption/thead, figure с содержательным
alt/figcaption, не менее двух технических
примеров и нумерованный маршрут в каждой revision;
- явное различение owner state, consumer projection, version gap, duplicate
event и compensation key;
- отсутствие claims о реальных заказах, замеренном lag, exactly-once,
production delivery и зрелой distributed platform;
- отсутствие анахронизма: источники и версия Kafka/PostgreSQL/CloudEvents
существовали к апрелю 2021 года, а паттерн не выдан за стандарт.
Вердикт прохода: **пройден**. Все три материала начинают с наблюдаемого
расхождения и цены, затем дают конкретный owner/инвариант/evidence/route.
Риторическая формулировка про «магический rollback» была заменена до финального
audit на точное описание ложной границы компенсации.
## Проход 3. Визуал, fixture и preflight — пройдено
Три SVG подготовлены как вертикальные схемы для 375 px:
- state machine отделяет owner v2/v3 от отложенной consumer projection;
- compensation показывает проверенный reason, локальный key и новое owner
решение;
- diagnosis ведёт от блока рискованного effect к evidence packet, version
branch и контролируемому действию.
Во всех SVG предусмотрены title, desc и
role="img"; отсутствуют JavaScript, foreignObject,
external URL и raster data URI. В первой статической проверке нижняя подпись
state machine оказалась слишком длинной для 375 px; она сокращена, SVG
отрендерен и просмотрен повторно.
cd web && node --check scripts/upgrade-2021-04.mjs
cd web && npm run audit:draft -- scripts/upgrade-2021-04.mjs
cd web && node scripts/upgrade-2021-04.mjs --verify-fixture
cd web && xmllint --noout \
public/assets/editorial/2021/data-consistency-state-machine-2021.svg \
public/assets/editorial/2021/data-consistency-compensation-2021.svg \
public/assets/editorial/2021/data-consistency-diagnosis-2021.svg
| Проверка | Реальный результат |
| --- | --- |
| node --check | PASS, code 0 |
| Import-safe export и draft gate | PASS: итоговые **10 294 / 10 790 / 11 728** знаков body; для всех трёх slug найдены sections, table, figure, code, route, sources и локальные SVG |
| In-memory fixture | PASS: итоговые десять assertions равны true; v3 сначала defer, затем v2 и replay v3; duplicate не меняет projection; другой event с занятой version отклоняется; компенсация записывается один раз; cancelled не разрешает effect |
| xmllint --noout | PASS, все три SVG — корректный XML |
| SVG safety scan | PASS: не найдены script, foreignObject, external URL или raster data URI |
| Sharp mobile preflight | PASS: финальные PNG 375×656, 375×667 и 375×719 просмотрены вручную; clipping, overlap и horizontal overflow внутри схем не обнаружены |
| Scope/self-review | PASS: созданы только пять разрешённых файлов; revision не меняют date/author; registry, archive, README, очередь, standard, package config, Git и чужие untracked files не редактировались |
npm run audit:draft завершилась с code 0. npm вывел старые
предупреждения о пользовательских store-dir, cache-dir
и public-hoist-pattern; они не относятся к П38 и не менялись
пакетом.
До независимой интеграции автономный автор не заявлял strict registry audit,
production build, browser, screen reader, database/broker/API checks,
deployment, commit или push.
## Независимая интеграционная приёмка
Основной редактор 31 июля 2026 года подключил три revision к
web/data/editorial-revisions.mjs, сохранив базовый
articles.json, даты и автора архивных записей. В registry стало
109 revision, строгий аудит проходит 118 из 358 материалов.
В независимом техническом проходе найден один риск в учебном guard: новый
event с уже занятой orderVersion, но с другим id,
мог бы изменить projection. До выпуска guard был уточнён: сначала проверяется
subject, затем такой event возвращает
same-version-event-rejected; конфликт в отложенной версии также
не перезаписывает evidence. Fixture получила десятый assertion, а механизм и
полевой маршрут — явное правило не выбирать конфликт по времени получения.
Это изменение не выдаётся за transport guarantee.
CloudEvents release record подтверждает выпуск 1.0.1 в декабре 2020 года;
версионная документация PostgreSQL 13 подтверждает границы локальной
изоляции и retry при serialization failure; Kafka 2.7 отдельно ограничивает
producer idempotence одной session и не дедуплицирует application-level
re-send. Эти источники сверены независимо и использованы только в названных
границах.
| Проверка после интеграции | Реальный результат |
| --- | --- |
| Import-safe export | PASS: три revision, без date/author |
| Строгий audit трёх slug | PASS: **10 294 / 10 790 / 11 728** знаков; у каждой статьи есть figure, table и code examples |
| Fixture после редакторского исправления | PASS: все 10 assertions истинны, включая rejection другого event с той же version |
| Независимый SVG review | PASS: XML и active/external asset scan прошли; три PNG 375 px просмотрены повторно, clipping, overlap и overflow не обнаружены |
| Production build | PASS: Next.js собрал 374 статические страницы |
Ни этот отчёт, ни интеграция не утверждают запуск broker, SDK, HTTP, базы,
external API, browser или assistive technology.
Выпусковой вердикт: **ACCEPT**. Commit и push выполняются отдельной
публикационной операцией; Git остаётся источником её фактической записи.