Перейти к содержимому
DedicatedPHP Контакт

Как безопасно приостанавливать и возобновлять автоматизацию на PHP

Продумайте безопасную приостановку PHP-процессов: сохраняйте точку продолжения, контролируйте, кто принимает решение, и не допускайте повторного выполнения операций при возобновлении.

Диаграмма потока PHP, приостановленного для вмешательства и возобновляемого из сохранённого состояния

Автоматизация может дойти до этапа, на котором нельзя продолжать без решения, данных или проверки. Например, перед подтверждением чувствительной операции может потребоваться одобрение или нужно дождаться информации, которую может предоставить только человек. В таких случаях система должна сохранять состояние, из которого можно продолжить работу, и объяснять, чего не хватает, а не просто останавливать текущее выполнение.

Чтобы спроектировать приостановку и возобновление автоматизации на PHP, нужно отделить состояние процесса от выполнения работы. Приостановка должна быть намеренной, сохраняться в хранилище и допускать аудит; при возобновлении необходимо проверять, что процесс по-прежнему актуален и уже выполненные действия не повторяются. Это не то же самое, что проектирование очереди на проверку: здесь главное — жизненный цикл потока и его безопасное продолжение.

Отличайте приостановку от ожидания и сбоя

Отличайте приостановку от ожидания и сбоя — guía visual de DedicatedPHP

Если процесс не продвигается, это не обязательно означает, что он приостановлен. Ожидание ответа на вызов API — это внешнее ожидание. Сетевая ошибка может быть основанием для повторной попытки. Невосстановимое исключение может завершить процесс с ошибкой. Намеренная приостановка, напротив, означает, что поток достиг известной точки и для продолжения или завершения требуется явное условие.

Отдельные состояния для каждой ситуации помогают избежать ошибочных операционных решений. Повторный запуск действия, ожидающего одобрения, может привести к ненужному повторному запросу; обработка штатной приостановки как сбоя может запустить неуместные оповещения или процедуры восстановления. Как минимум, определите отдельные состояния для выполнения, внешнего ожидания, необходимости вмешательства, завершения, отмены и сбоя. Если по бизнес-правилам приостановка должна переставать быть действительной по истечении срока, добавьте срок действия.

Прежде чем добавлять приостановку, определите, что её вызывает и кто может её разрешить. Ожидающая задача, которая завершается автоматически после получения ответа, не всегда требует вмешательства человека. Оно может понадобиться, если решение влияет на финансы, юридические обязательства, доступ или безопасность. От этого зависит, кто может действовать, какие свидетельства нужно сохранить и что произойдёт, если ответа не будет.

Сохраняйте состояние и точку продолжения

Процесс должен переживать завершение PHP-запроса, перезапуск воркера и выпуск новой версии сервиса. Сохраняйте в постоянном хранилище стабильный идентификатор, текущее состояние, достигнутый этап, причину приостановки, ссылки на необходимые данные и важные временные метки. Когда это уместно, также записывайте, кто приостановил процесс или разрешил продолжение, и какое решение было принято.

Не ограничивайтесь сообщением вроде «ожидание одобрения». Оно не указывает, какое выполнение остановлено, с какого этапа нужно продолжить и не изменились ли данные. Вместо этого представьте приостановку как часть модели процесса и сохраните достаточно контекста, чтобы проверить возможность возобновления. По возможности храните ссылки на чувствительную информацию, а не дублируйте данные без необходимости; применяйте соответствующие характеру этих данных правила доступа и хранения.

Определите допустимые переходы и проверяйте их на сервере. Например, процесс в состоянии «требуется вмешательство» может перейти к выполнению, отмене или истечению срока; завершённый процесс не должен возвращаться к выполнению через обычный запрос. PHP-функция может проверять переход, но это правило нужно защищать и от конкурентного доступа на уровне базы данных, а не только в интерфейсе.

Разделяйте регистрацию процесса и выполнение

Регистрация необходимости продолжить процесс и выполнение его этапов связаны, но это не одна и та же операция. Если обновить состояние, а затем процесс завершится до начала работы, поток может застрять. Если начать работу до сохранения перехода, повторный запуск может выполнить тот же этап ещё раз. Спроектируйте координацию так, чтобы по сохранённому состоянию можно было восстановить незавершённую работу.

Один из распространённых вариантов — сохранить переход и инструкцию на продолжение в одной транзакции базы данных, например, используя паттерн transactional outbox. Отдельный воркер читает эту инструкцию и выполняет следующий этап. Конкретный выбор зависит от архитектуры; важно, чтобы система могла обнаружить необработанную работу и восстановить её, а не рассчитывала на то, что веб-запрос останется активным.

Внешние эффекты требуют особого внимания. Локальная транзакция сама по себе не может отменить отправленное письмо, подтверждённое списание или вызов, уже принятый другим сервисом. По возможности проектируйте каждый этап с ключом идемпотентности, сохраняйте результат до перехода к следующему этапу и предусмотрите сверку или компенсацию, если операцию нельзя безопасно повторить. Не помечайте этап завершённым, пока не станет известен результат.

Контролируйте возобновление, отмену и истечение срока

При возобновлении необходимо проверить актуальное состояние, личность и права инициатора, а также выполнение всех необходимых условий. Недостаточно показать кнопку уполномоченному человеку: сервер должен повторно проверить всё при получении запроса. Если для решения требуется обоснование или дополнительные данные, проверьте и сохраните их как часть разрешения.

Отмену и истечение срока тоже следует оформлять как явные переходы, а не как удаление записи. При отмене нужно запретить дальнейшие этапы и указать, есть ли уже выполненные действия, которые нельзя отменить. Для истечения срока необходимо определить дальнейшие действия: завершить процесс, запросить новое вмешательство или направить случай для выполнения другого действия. Поведение зависит от бизнес-правила и должно быть понятно операционной команде.

Повторные запросы и гонки — обычное явление: человек может нажать кнопку дважды, а два участника могут действовать почти одновременно. Используйте условное обновление, блокировку или контроль версии, чтобы применился только один допустимый переход. На второй запрос нужно отвечать в соответствии с текущим состоянием, не выполняя эффекты повторно. Сохраняйте идентификатор операции или ключ идемпотентности, чтобы распознавать повторы.

Сделайте приостановку понятной и проверяемой

Операционный интерфейс должен объяснять, почему процесс остановлен, какой этап ожидает выполнения, какой информации не хватает, кто может действовать и к чему приведёт каждый вариант. Не используйте неоднозначные кнопки и действия, одновременно объединяющие одобрение, исправление данных и продолжение. Показывайте только сведения, необходимые для принятия решения, и ограничивайте доступ в соответствии с ролью. История переходов помогает отличить штатное ожидание от заблокированного или неправильно настроенного процесса.

Проверьте поток на сбоях до и после каждого внешнего эффекта. Убедитесь, что перезапуск не приводит к потере приостановки, повторное возобновление не дублирует действия, а отмена блокирует последующие этапы. Проверьте также сценарии, в которых данные изменились во время остановки, права были отозваны, срок истёк, ответ поступил с опозданием или одновременно пришли два запроса. Проверьте журналы и оповещения: по ним должно быть возможно найти процесс и понять следующий шаг, не раскрывая секреты.

Контрольный список для выбора поведения

Контрольный список для выбора поведения — guía visual de DedicatedPHP
  • Ожидать: внешний ответ ещё не получен, и система может продолжить работу автоматически после его поступления; при этом определены временные ограничения и способы восстановления.
  • Приостановить для вмешательства: перед выполнением следующих этапов требуется явное решение человека или предоставленные им данные.
  • Повторить попытку: произошёл временный сбой, и повторный запуск этапа безопасен или защищён механизмом идемпотентности.
  • Завершить: допустимого продолжения нет либо процесс завершён, отменён, срок его действия истёк или произошёл окончательный сбой.

Перед выпуском потока убедитесь, что каждый переход разрешён, состояние сохраняется, ранее выполненные действия не повторяются и команда знает, как устранить причину приостановки. Если вы не можете ответить, что именно будет возобновлено, с какими данными и при каких условиях, у процесса ещё нет безопасной точки продолжения.

Хотите применить эти идеи в своем проекте?Давайте обсудим вашу PHP-платформу.
Посмотреть связанные услуги