14 KiB
Май 2020 — тройное ревью автономного пакета P27 «Фоновые задачи»
Статус: принят в publication registry 31 июля 2026 года. Он включает ровно три revision для стабильных slug; registry сохраняет дату и автора базового архива:
editorial-2020-05-practice-background-jobs;editorial-2020-05-mechanism-background-jobs;editorial-2020-05-field-background-jobs.
В module export нет полей date и author;
articles.json, standard, очередь и package config не
перезаписывались. При вызове --print-revisions stdout
содержит только JSON, а --verify-fixture запускает отдельную
детерминированную учебную фикстуру.
Проход 1. Факты, состояния и границы механизма — пройдено
| Утверждение | Первичный или официальный источник | Редакторская граница |
|---|---|---|
Delivery tag относится к доставке, а basic.ack и basic.reject относятся к этой доставке |
AMQP 0-9-1 specification | Тексты не используют delivery tag как вечный идентификатор задачи и не приписывают абстрактному псевдокоду API конкретной Node-библиотеки. |
| Неподтверждённая ручная delivery возвращается после закрытия канала/соединения; requeue может образовать дорогой loop | RabbitMQ: Consumer Acknowledgements and Publisher Confirms | redelivered используется как сигнал в журнале, но идемпотентность опирается на jobId и terminal state, а не на один флаг. |
| Publisher/consumer неопределённость допускает duplicate, поэтому consumer должен быть идемпотентен либо делать deduplication | RabbitMQ: Reliability guide | Материалы утверждают только at-least-once контракт одной задачи; exactly-once не обещается. |
reject/nack без requeue может направить сообщение в dead-letter route при настроенном DLX |
RabbitMQ: Dead Letter Exchanges | Карантин описан как проверяемый маршрут конкретной конфигурации. Не заявлено, что он существует без настройки или одинаково работает у любого broker. |
Внутри статей разделены четыре факта, которые часто смешивают: запись
намерения в базе, outbox-публикация, delivery worker-у и сохранённый бизнес-
результат. Для одного jobId описаны состояния
queued, running, retry_wait,
succeeded и quarantined. Ack следует после
сохранения resultKey и terminal state. Повтор до этого момента
не считается дефектом: повторный worker должен увидеть завершённую задачу и
подтвердить новое delivery без второго effect.
Проверена и намеренно оставлена граница внешнего side effect. Детерминированный
путь reports/{jobId}.csv демонстрирует идемпотентность одного
экспорта; он не делает идемпотентными 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 знака |
- Во всех трёх текстах первый абзац называет конкретный симптом и его цену, а второй очерчивает учебную границу. Далее выдержан маршрут «симптом → причина → проверка → действие → ограничение», без общей техлид-риторики.
- У каждой статьи есть не менее пяти смысловых разделов, таблица с
caption/thead, рисунок с самостоятельнымиaltиfigcaption, код или JSON-журнал, нумерованный маршрут и четыре первичных/официальных источника. - Практика объясняет outbox и порядок результата/ack. Механизм отделяет
delivery tag от
jobId, вводит 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 — пройдено в пределах пакета
background-job-lifecycle-2020.svgпоказывает вертикальный путь от записи job/outbox к worker, сохранённому result, ack, retry и quarantine/DLX.background-job-retry-boundary-2020.svgотделяет delivery tag от terminal state и показывает, что временный retry ограничен, а постоянная ошибка останавливается без requeue.background-job-diagnosis-2020.svgведёт расследование по одномуjobIdчерез запись задачи, outbox, журнал worker, resultKey и карантин.- Все схемы имеют
title,desc,role="img", вертикальный viewBox, короткие подписи и контрастные карточки. В них нет JavaScript,foreignObject, внешних 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-интеграционный тест.
Учебная фикстура --verify-fixture выполнила две цепочки в памяти:
временный отказ → повторная delivery → result → ack и три неуспеха →
quarantined. Она вернула три истинных условия: ackAfterResult,
poisonStopped и retryWasRedelivered. Фикстура не
подключалась к RabbitMQ, не проверяла AMQP frames, DLX policy, сеть, несколько
consumer, скорость или production workload.
Фактически выполненные проверки
| Проверка | Команда | Реальный результат |
|---|---|---|
| Синтаксис модуля | node --check scripts/upgrade-2020-05.mjs из web/ |
PASS, код 0 |
| Import-safe export и draft gate | npm run audit:draft -- scripts/upgrade-2020-05.mjs из web/ |
PASS: 9 385 / 10 550 / 10 484 знаков body; три slug, таблицы, figures, code, routes, sources и assets найдены |
| Учебная фикстура состояний | node scripts/upgrade-2020-05.mjs --verify-fixture из web/ |
PASS: ackAfterResult, poisonStopped, retryWasRedelivered — true |
| XML трёх схем | 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 из web/ |
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 | |
npm run build |
PASS, code 0, 374 статические страницы | |
| Scope/self-review | PASS: в revision нет date/author, а articles.json не перезаписан |
Выпусковой вердикт: тройное ревью пройдено, пакет принят к публикации. Registry заменяет только редакционные поля по стабильному slug. Реальный broker, DLX policy, browser и assistive-tech не запускались и не выданы за результат in-memory fixture или статической сборки.