Files
progcode/editorial/reviews/2020-05-draft.md
T
huncode 406e60bf44
Build and deploy / deploy (push) Successful in 13s
revise May 2020 background job articles
2026-07-31 11:27:15 +03:00

134 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Май 2020 — тройное ревью автономного пакета P27 «Фоновые задачи»
Статус: **принят в publication registry 31 июля 2026 года**. Он включает
ровно три revision для стабильных slug; registry сохраняет дату и автора
базового архива:
- <code>editorial-2020-05-practice-background-jobs</code>;
- <code>editorial-2020-05-mechanism-background-jobs</code>;
- <code>editorial-2020-05-field-background-jobs</code>.
В module export нет полей <code>date</code> и <code>author</code>;
<code>articles.json</code>, standard, очередь и package config не
перезаписывались. При вызове <code>--print-revisions</code> stdout
содержит только JSON, а <code>--verify-fixture</code> запускает отдельную
детерминированную учебную фикстуру.
## Проход 1. Факты, состояния и границы механизма — пройдено
| Утверждение | Первичный или официальный источник | Редакторская граница |
| --- | --- | --- |
| Delivery tag относится к доставке, а `basic.ack` и `basic.reject` относятся к этой доставке | [AMQP 0-9-1 specification](https://www.rabbitmq.com/resources/specs/amqp-xml-doc0-9-1.pdf) | Тексты не используют delivery tag как вечный идентификатор задачи и не приписывают абстрактному псевдокоду API конкретной Node-библиотеки. |
| Неподтверждённая ручная delivery возвращается после закрытия канала/соединения; requeue может образовать дорогой loop | [RabbitMQ: Consumer Acknowledgements and Publisher Confirms](https://www.rabbitmq.com/docs/3.13/confirms) | `redelivered` используется как сигнал в журнале, но идемпотентность опирается на `jobId` и terminal state, а не на один флаг. |
| Publisher/consumer неопределённость допускает duplicate, поэтому consumer должен быть идемпотентен либо делать deduplication | [RabbitMQ: Reliability guide](https://www.rabbitmq.com/docs/reliability) | Материалы утверждают только at-least-once контракт одной задачи; exactly-once не обещается. |
| `reject`/`nack` без requeue может направить сообщение в dead-letter route при настроенном DLX | [RabbitMQ: Dead Letter Exchanges](https://www.rabbitmq.com/docs/next/dlx) | Карантин описан как проверяемый маршрут конкретной конфигурации. Не заявлено, что он существует без настройки или одинаково работает у любого broker. |
Внутри статей разделены четыре факта, которые часто смешивают: запись
намерения в базе, outbox-публикация, delivery worker-у и сохранённый бизнес-
результат. Для одного <code>jobId</code> описаны состояния
<code>queued</code>, <code>running</code>, <code>retry_wait</code>,
<code>succeeded</code> и <code>quarantined</code>. Ack следует после
сохранения <code>resultKey</code> и terminal state. Повтор до этого момента
не считается дефектом: повторный worker должен увидеть завершённую задачу и
подтвердить новое delivery без второго effect.
Проверена и намеренно оставлена граница внешнего side effect. Детерминированный
путь <code>reports/{jobId}.csv</code> демонстрирует идемпотентность одного
экспорта; он не делает идемпотентными email, платёж, сторонний API или любое
другое необратимое действие. Для него нужен собственный стабильный ключ и
контракт принимающей стороны. Outbox также не выдан за распределённую
транзакцию с broker: он оставляет приложению восстанавливаемую запись на
публикацию, а реальный confirm зависит от выбранного клиента и стенда.
Историческая граница сохранена: это М3 / май 2020. Автор уже связывает backend
и delivery — состояние задачи, outbox, worker, retry и журнал — но не
приписывает себе платформу observability, современную оркестрацию или
универсальную реализацию задержанных очередей. Современная официальная
документация использована для сверки смысла протокольных операций, а не как
заявление о конкретно запущенной инфраструктуре мая 2020 года.
Вердикт прохода: **пройден**. Механизм и его технологические допущения
разделены; учебная фикстура не выдана за реальный broker.
## Проход 2. Редактура, глубина и голос М3 — пройдено
| Ревизия | Проблема и цена в первых двух абзацах | Практический вопрос | Объём по publication draft gate |
| --- | --- | --- | --- |
| Практика | Экспорт исчезает или создаёт дубль; цена — потерянная работа, неверный статус и ручной разбор | Как зафиксировать намерение, outbox, result и ack в одном коротком контракте | **9 385** знаков |
| Механизм | Команда смешивает job и delivery; цена — ранний ack, дубль effect или бесконечный requeue | Почему ack ставится после результата и как один `jobId` переживает повтор | **10 550** знаков |
| Полевой разбор | Один экспорт дублируется, невалидная задача крутится; цена — лишний effect, перегруженный worker и скрытая причина | Как расследовать один `jobId` и остановить poison message | **10 484** знака |
- Во всех трёх текстах первый абзац называет конкретный симптом и его цену, а
второй очерчивает учебную границу. Далее выдержан маршрут «симптом → причина
→ проверка → действие → ограничение», без общей техлид-риторики.
- У каждой статьи есть не менее пяти смысловых разделов, таблица с
<code>caption</code>/<code>thead</code>, рисунок с самостоятельными
<code>alt</code> и <code>figcaption</code>, код или JSON-журнал,
нумерованный маршрут и четыре первичных/официальных источника.
- Практика объясняет outbox и порядок результата/ack. Механизм отделяет
delivery tag от <code>jobId</code>, вводит retry-политику и quarantine.
Полевой текст не притворяется реальным incident: все ID, журналы и результат
маркированы как анонимизированная фикстура.
- Никакой текст не предлагает «повторить всё» или «увеличить timeout» без
классификации. Временная, неопределённая внешняя и постоянная ошибка имеют
разные проверки и разные следующие действия.
Отдельный редакторский контроль подтвердил, что исходные названия заметно
конкретизированы: в заголовках и excerpts есть job, worker, ack, retry,
идемпотентность и poison message, а не яркий общий заголовок с коротким
содержимым. Диапазон 5 000–15 000 соблюдён собственным guard модуля без
таблиц, code blocks и figures; строгий draft gate дополнительно измерил
видимое тело с этими артефактами.
Вердикт прохода: **пройден**. Глубина достигнута через разбор границ и
проверяемый маршрут, голос остаётся прагматичным уровнем М3.
## Проход 3. Визуал, фикстура и выпусковой preflight — пройдено в пределах пакета
- <code>background-job-lifecycle-2020.svg</code> показывает вертикальный
путь от записи job/outbox к worker, сохранённому result, ack, retry и
quarantine/DLX.
- <code>background-job-retry-boundary-2020.svg</code> отделяет delivery tag
от terminal state и показывает, что временный retry ограничен, а постоянная
ошибка останавливается без requeue.
- <code>background-job-diagnosis-2020.svg</code> ведёт расследование по одному
<code>jobId</code> через запись задачи, outbox, журнал worker, resultKey и
карантин.
- Все схемы имеют <code>title</code>, <code>desc</code>,
<code>role="img"</code>, вертикальный viewBox, короткие подписи и контрастные
карточки. В них нет JavaScript, <code>foreignObject</code>, внешних URL или
raster data URI.
- Независимый mobile preflight отрендерил каждый SVG через Sharp в PNG шириной
375 px и просмотрел результат. На первом рисунке длинная последняя подпись
была развёрнута в две строки, на втором короткая tag-подпись была сокращена;
после правки обрезания, наложения и горизонтального выхода в SVG не осталось.
Это статическая проверка visual asset, не browser-run и не тест screen reader.
- Основной редактор отдельно просмотрел финальные raster-версии на 375 px и
подтвердил вывод. После подключения registry strict audit и production build
пройдены; они не подменяют настоящий broker-интеграционный тест.
Учебная фикстура <code>--verify-fixture</code> выполнила две цепочки в памяти:
временный отказ → повторная delivery → result → ack и три неуспеха →
quarantined. Она вернула три истинных условия: <code>ackAfterResult</code>,
<code>poisonStopped</code> и <code>retryWasRedelivered</code>. Фикстура не
подключалась к RabbitMQ, не проверяла AMQP frames, DLX policy, сеть, несколько
consumer, скорость или production workload.
### Фактически выполненные проверки
| Проверка | Команда | Реальный результат |
| --- | --- | --- |
| Синтаксис модуля | <code>node --check scripts/upgrade-2020-05.mjs</code> из <code>web/</code> | PASS, код 0 |
| Import-safe export и draft gate | <code>npm run audit:draft -- scripts/upgrade-2020-05.mjs</code> из <code>web/</code> | PASS: 9 385 / 10 550 / 10 484 знаков body; три slug, таблицы, figures, code, routes, sources и assets найдены |
| Учебная фикстура состояний | <code>node scripts/upgrade-2020-05.mjs --verify-fixture</code> из <code>web/</code> | PASS: `ackAfterResult`, `poisonStopped`, `retryWasRedelivered` — true |
| XML трёх схем | <code>xmllint --noout public/assets/editorial/2020/background-job-lifecycle-2020.svg public/assets/editorial/2020/background-job-retry-boundary-2020.svg public/assets/editorial/2020/background-job-diagnosis-2020.svg</code> из <code>web/</code> | PASS, код 0 |
| Mobile visual preflight | Sharp render трёх SVG в PNG шириной 375 px и ручной просмотр | PASS после точечной правки двух коротких подписей; нет clipping, наложения или horizontal overflow внутри SVG |
| Strict audit после подключения registry | PASS: 9 385 / 10 550 / 10 484 знаков; 2 / 2 / 2 table и 1 / 2 / 2 code example |
| <code>npm run build</code> | PASS, code 0, 374 статические страницы |
| Scope/self-review | PASS: в revision нет date/author, а <code>articles.json</code> не перезаписан |
Выпусковой вердикт: **тройное ревью пройдено, пакет принят к публикации**.
Registry заменяет только редакционные поля по стабильному slug. Реальный
broker, DLX policy, browser и assistive-tech не запускались и не выданы за
результат in-memory fixture или статической сборки.