Передача длительного процесса и пределы восстановления
«Согласование» теперь имеет ожидание редактора, устойчивое время, повторы внешних операций, идемпотентность, отмену, компенсацию и совместимое изменение кода. Завершим серию передачей проекта. Основной результат — сделать понятными состояние данных, выбор Workflow-стадии и действия при неопределённом внешнем эффекте, не скрывая невыполненные проверки.
Все материалы написаны локально. Автор не устанавливал пакеты, не собирал TypeScript, не запускал Temporal Service, gateway, Worker, Activities или replay. Тесты и публикация также не выполнялись. Метаданные example_execution: not_run, README и план серии сохраняют этот статус рядом с исходниками.
Передаём совместимый набор файлов
Финальный Worker по умолчанию выбирает 11-versioned. Package.json закрепляет SDK 1.24.0, tsconfig определяет CommonJS-сборку, contracts.ts сохраняет имена заявки и решения. Для изучения ранней стадии есть отдельные полные Workflow-файлы. Следующий разработчик не должен смешивать их по случайным фрагментам из разных уроков.
Таблица состояний в README связывает номер урока с WORKFLOW_STAGE. Для новой учебной стадии используют новый submissionId. Исключение — специально описанный совместимый переход 09 на 11 через patched. Это явная граница: наличие всех файлов в одном архиве не обещает совместимость любых уже записанных историй.
Собранный Workflow bundle или dist-файлы в комплект не включены, поскольку build не выполнялся. После самостоятельной установки и сборки читатель фиксирует lock-файл, версии Node и CLI и полученный набор артефактов. Нельзя написать «проект готов к продакшену» по наличию package.json без фактического исполнения необходимых проверок.
Адрес Temporal Service 127.0.0.1:7233, namespace default, Task Queue soglasovanie и editorial gateway 127.0.0.1:7070 относятся к локальной лаборатории. Реальный внешний сервис и производственные credentials требуют другой конфигурации. Не следует заменять loopback на рабочий адрес лишь для того, чтобы учебная команда «показала результат».
Два независимых хранилища
Temporal Service хранит history и состояние исполнения. Gateway хранит reservations, publications и receipts в editorial-data/state.json. Worker исполняет код, но его память не является единственным источником этих данных. Для обычного восстановления лаборатории нужно сохранить оба соответствующих состояния.
Удаление temporal.db теряет локальную историю, даже если JSON gateway остался. Удаление editorial-data теряет публикации и квитанции, даже если Temporal помнит успешный publish. Поэтому резервная копия одной стороны не заменяет восстановление другой. Согласованный регламент должен учитывать связи по submissionId, revision и operation key.
В учебном gateway нет производственной транзакционной базы, нескольких реплик и гарантий fsync при потере питания. Этот факт записан в README, а не спрятан в последней строке урока. Реальное приложение должно сохранять эффект и квитанцию согласованно, обеспечивать конкуренцию и иметь собственную процедуру резервного копирования.
Операционная история тоже содержит данные: title и editor пришли в args и Signal. Доступ к history, сроки retention и возможное кодирование данных относятся к архитектуре продукта. Действующие секреты не передают в payload ради простоты; Activity может использовать защищённое окружение Worker, не превращая credential в результат Workflow.
Наблюдение и ручное решение
При инциденте сначала сохраняют Workflow ID и Run ID. Затем определяют, какой шаг подтверждён, какой ожидает и какая версия Worker должна обработать историю. Неправильная очередь, недоступный исполнитель и ошибка gateway могут одинаково выглядеть для пользователя как долгое ожидание, но требуют разных действий.
Query status показывает внутреннюю стадию процесса, однако нуждается в подходящем исполнителе и не является таблицей всех заявок. Для списка материалов в настоящем интерфейсе часто нужна отдельная проекция. Она должна различать предметный результат и технический инцидент, чтобы expired не превращался в скрытую failed-публикацию.
ManualIntervention означает неподтверждённый cleanup. Оператор сверяет внешние reservations, publications и receipts. Если publication существует, releaseSlot не удалит её. Если брони нет, повторное освобождение безопасно. Предметное решение об отзыве материала относится к отдельным полномочиям и процессу, которого в учебном наборе нет.
Cancel и terminate тоже различаются в передаче. Cancel позволяет Workflow исполнить предусмотренную cleanup-ветку; terminate такой возможности не гарантирует. Принудительное закрытие не должно становиться обычной пользовательской кнопкой «отменить». Регламент обязан объяснять последствия для внешних ресурсов.
Когда требуется Continue-As-New
Один согласуемый материал имеет конечный набор действий. Его history не нужно искусственно обнулять после каждого Signal. Но постоянно живущая сущность, которая получает множество сообщений, накапливает события. Temporal ограничивает объём history, поэтому для такого процесса рассматривают Continue-As-New.
Continue-As-New завершает текущий run и начинает новый с тем же Workflow ID и новым Run ID, передавая необходимое состояние как вход. Это не restart Worker и не удаление данных gateway. Предметное состояние нужно выбрать явно: какую revision продолжаем, какие решения приняты и какие операции уже завершены.
Перед переходом нужно согласовать незавершённые обработчики и входящие сообщения. Нельзя продолжить новым run, забыв ожидающее решение редактора, а затем объявить потерю нормальным способом очистки истории. Механизм и требования описаны в документации Continue-As-New.
Наш финальный Workflow Continue-As-New не использует, потому что процесс конечный. Это осознанное отсутствие, а не пропущенная обязательная строка. Если проект превратится в постоянно живущий редакционный inbox, потребуется другая граница сущности, проекция состояния и протокол переноса сообщений.
Будущая приёмка по предметным исходам
Самостоятельная проверка должна показать обычное одобрение, отказ, отсутствие решения, отмену ожидания и потерю ответа publish. Для каждой ветки важны не только завершённый Workflow, но и состояние gateway: publication либо отсутствует, либо подтверждена, бронь освобождена или потреблена, receipt соответствует стабильному ключу.
Отдельно проверяется restart Worker и совместимость старой history при переходе 09 на 11. Replay показывает определённую совместимость событий, а реальные Activities — работу внешнего контракта. Один результат не заменяет другой. Здесь эти действия запланированы для читателя и не выданы за уже выполненный комплект тестов.
Хорошая передача сохраняет и ограничения: локальный dev-server, один gateway-процесс, отсутствие реальной авторизации редактора, неисполненный replay и отдельная ответственность за отзыв публикации. Они помогают оценить следующую работу, а не уменьшают ценность изученного механизма.
Оглавление «Temporal: длительные процессы и восстановление после сбоев» связывает все двенадцать этапов. После самостоятельного прохода читатель сможет дополнить регламент фактическими версиями, экспортированными историями и наблюдениями своей лаборатории. Тогда длительный процесс будет сопровождаться проверяемыми данными, а не только обещанием автоматического восстановления.