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

Оценивать следует влияние операции, а не применять правило, основанное только на её длительности. Кандидатом на выполнение в фоне может быть задача с переменным временем выполнения, ожиданием ответа внешней системы или обработкой большого количества элементов. Например, это может быть создание большого отчёта, импорт файла, преобразование документов или синхронизация данных с API.
Однако если пользователю для продолжения нужна немедленная проверка — например, проверка обязательного значения перед сохранением, — эту часть, возможно, лучше оставить в запросе, а в фон вынести только последующую работу. Есть и медленные задачи, для которых по бизнес-требованиям необходим синхронный ответ. Архитектура должна соответствовать потребностям процесса, а не превращать каждую операцию в асинхронную задачу.
Прежде чем менять архитектуру, выясните, сколько времени занимает операция, какая её часть требует этого времени и что произойдёт в случае сбоя. Очередь сама по себе не исправит неэффективные запросы, неправильно настроенные лимиты или нестабильные внешние зависимости; она может лишь перенести эти проблемы на фоновых обработчиков.
Сообщайте о принятии задачи, а не о выдуманном результате
Если задача принята для последующего выполнения, ответ приложения должен чётко различать состояния принята и завершена. Можно вернуть идентификатор задачи и указать, что обработка ожидает начала. Нельзя представлять результат, которого ещё нет, как готовый.
Оценку длительности следует показывать, только если данных достаточно для её расчёта и можно сообщить о неопределённости. Во многих системах честнее показать состояние «в очереди» или «обрабатывается», чем обещать время завершения. Если задача может выполниться быстро, интерфейс всё равно может проверять её состояние и показать результат, когда он будет готов, не блокируя исходный запрос.
Также определите, что произойдёт, если отправить задачу в очередь не удастся: приложение не должно подтверждать её принятие, если не может надёжно зарегистрировать задачу. Конкретный механизм зависит от архитектуры, но ответ и сохранённое состояние должны быть согласованы.
Определите состояния и допустимые переходы
Небольшой и явно заданный жизненный цикл упрощает взаимодействие с пользователем и эксплуатацию. В качестве основы можно использовать состояния pendiente, en_proceso, cancelacion_solicitada, completada, fallida и cancelada. Эти названия приведены для примера и могут различаться; переходы же должны быть допустимыми и проверяемыми, а не произвольной комбинацией состояний.
- Обычные переходы:
pendiente → en_proceso, а из состоянияen_proceso— вcompletadaилиfallida. - Отмена до начала выполнения:
pendiente → cancelada, если подтверждено, что обработчик ещё не приступил к задаче. - Отмена во время выполнения:
en_proceso → cancelacion_solicitada. Из этого состояния задача переходит вcancelada, если её удалось безопасно остановить; вcompletada, если она завершилась до обработки запроса; или вfallida, если произошёл сбой. - Конечные состояния:
completada,fallidaиcanceladaне должны возвращаться в активные состояния. Если задачу можно повторить, создайте новый запуск или явно определите отдельный цикл.
Система должна запрещать недопустимые переходы и регистрировать время каждого изменения. Если работа обработчика прерывается и задача остаётся в состоянии en_proceso, не отмечайте её автоматически как завершённую. Политика восстановления может вернуть её в состояние pendiente, если безопасно продолжить выполнение, или отметить как fallida для последующей проверки. Решение зависит от того, можно ли продолжить работу без дублирования побочных эффектов. Повторные попытки и идемпотентность требуют отдельных решений; их не следует смешивать с видимой пользователю моделью состояний.
Сообщайте о прогрессе, результате и ошибках
Прогресс должен опираться на измеримые этапы. Если достоверно рассчитать процент выполнения невозможно, лучше сообщать о текущем этапе («проверка данных», «создание отчёта») или оставить состояние «выполняется». Процент, который долго не меняется или без объяснения уменьшается, подрывает доверие.
После завершения предоставьте бизнес-результат: например, сводку по обработанным элементам или ссылку на созданный ресурс — с учётом прав доступа и доступности. Состояние задачи не обязано хранить весь результат. Вместо этого в нём можно сохранить ссылку на данные, которыми управляет предметная область приложения.
При сбое покажите сообщение, которое поможет определить следующий шаг, например исправить файл или повторить попытку, если это уместно. Техническую информацию об ошибке, необходимую для диагностики, регистрируйте отдельно и ограничьте доступ к ней. Не раскрывайте трассировки, учётные данные, внутренние пути и конфиденциальные данные в интерфейсе или публичном API.
Рассматривайте отмену как запрос с ограничениями
Запрос на отмену задачи не всегда означает, что её можно немедленно остановить. Обработчик может выполнять внешний вызов, записывать данные или находиться на этапе, который нельзя безопасно прервать. Поэтому интерфейс должен различать состояния cancelacion_solicitada и cancelada: первое означает, что запрос получен, второе — что система подтвердила остановку.
Реализация может проверять сигнал отмены в безопасных точках и не запускать последующие этапы. Если действие уже подтверждено во внешней системе, нельзя утверждать, что оно отменено. Объясните пользователю, какого результата ожидать, и, если это важно для аудита, регистрируйте, кто запросил отмену.
Разделяйте запись о задаче и бизнес-результат
Запись о задаче нужна для координации выполнения и проверки состояния; она может содержать идентификатор, состояние, даты, инициатора и ссылки на диагностические данные. Бизнес-результат — например, отчёт или импортированные записи — относится к модели данных, представляющей этот результат.
Такое разделение не позволяет временным данным задачи стать единственным источником бизнес-информации. Кроме того, оно помогает определить сроки хранения: как долго сохранять состояние, когда удалять файл и какие данные необходимо оставить по операционным или нормативным требованиям. Для устаревших состояний нужна политика очистки, иначе они будут накапливаться.
Защищайте запросы состояния и ограничивайте расход ресурсов
Для проверки задачи требуется авторизация, как и для доступа к любому другому ресурсу. Идентификатор не заменяет контроль доступа: проверяйте, имеет ли запрашивающий пользователь или система право видеть эту задачу и её результат. Также ограничивайте частоту и количество запросов, чтобы избежать чрезмерного опроса; если сценарий использования не требует постоянных обновлений, рассмотрите возможность уведомлений.
Для выполнения задач задайте лимиты параллелизма и ресурсов, соответствующие типу работы. Слишком большое количество обработчиков может перегрузить базу данных, внешние сервисы или хранилище; слишком малое — привести к накоплению задач и задержкам результатов. Отслеживайте объём очереди, возраст задач и длительность выполнения, а также ошибки. Эти показатели помогают отличить медленную зависимость от нехватки вычислительных ресурсов или пропускной способности.
Проверьте полный цикл до развёртывания
Приёмочные тесты должны проверять видимое пользователю поведение и сохранение состояния, а не только вызов обработчиком некоторой функции. Как минимум проверьте следующие сценарии:
- Запрос создаёт задачу и возвращает ссылку на неё или её идентификатор, не утверждая, что она уже завершена.
- Для завершённой задачи отображается конечное состояние, а пользователь с нужными правами может получить доступ к результату.
- Для задачи, завершившейся ошибкой, отображается безопасное сообщение, а диагностическая информация доступна авторизованной команде.
- Заброшенная или прерванная задача не остаётся бесконечно в состоянии «выполняется»; предусмотрен способ обнаружить её и принять меры.
- Запрос на отмену учитывает безопасные этапы и не обещает отменить уже выполненные действия.
В существующей системе вносите изменение для ограниченного набора операций и также проверьте, как работает пользовательский сценарий при задержках в очереди или её недоступности. В таких ситуациях приложение должно дать понятный ответ: сообщить, что не удалось принять задачу, предложить подходящий альтернативный порядок действий или позволить пользователю повторить попытку. Выбор зависит от влияния операции и гарантий, которые может обеспечить бизнес.
Контрольный список для внедрения очереди в существующую систему

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



