Вы читаете предварительную версию v0.1. API могут измениться.
~ 2 мин чтенияОбновлено 2026-10-29

Фоновые задания и планирование

Выполняйте медленные операции вне HTTP-запросов. Elang предоставляет очередь заданий с JSON-данными в базе данных, отложенные задания, ограниченные повторные попытки, просмотр неудачных заданий и планирование по UTC. Одно подключение к базе данных позволяет совместно зафиксировать изменение данных приложения и добавление соответствующего задания в очередь.

Подготовка служебных таблиц

Стартовые проекты аутентификации, блога, панели управления и API включают миграцию. В другом приложении выполните:

php elang queue:setup

Проверьте изменения схемы перед использованием --force в рабочей среде. SQLite удобен локально. Для нескольких серверов приложения используйте общую базу данных MySQL или PostgreSQL.

Регистрация обработчика

Регистрируйте обработчики при начальной загрузке приложения или в провайдере сервисов. HTTP-процессы и обработчики очереди должны загружать одинаковые регистрации. Полезная нагрузка содержит данные JSON; Elang никогда не десериализует объекты PHP и не принимает имя класса из данных задания.

use Elang\Queue\Jobs;
use Psr\Log\LoggerInterface;

$app->container->get(Jobs::class)->register(
    'reports.generate',
    function (array $payload, LoggerInterface $logger): void {
        // Load the record by ID and authorize the business operation here.
        $logger->info('Report requested', ['report_id' => $payload['report_id']]);
    }
);

Добавление и выполнение заданий

use Elang\Queue\Queue;

$id = $app->container->get(Queue::class)->push(
    'reports.generate',
    ['report_id' => 42],
    delay: 10
);
php elang queue:work
php elang queue:work --once
php elang queue:work --stop-when-empty --max-jobs=100
php elang queue:failed
php elang queue:retry JOB_ID

Задания резервируются с помощью условного обновления базы данных и токена резервирования. Гарантия доставки — как минимум один раз: аварийное завершение обработчика очереди или истечение срока резервирования может привести к новой попытке. Делайте обработчики идемпотентными с помощью уникальных ограничений на уровне приложения и ключей идемпотентности внешних провайдеров.

По умолчанию срок резервирования составляет 120 секунд, а максимальное число попыток — пять. Настройте queue.lease_seconds и queue.max_attempts в config/app.php. Длительность обработчика должна быть меньше срока резервирования; тайм-ауты диспетчера процессов также задавайте меньше этого срока, а долгие отчёты разбивайте на ограниченные части. Elang не прерывает выполняющийся PHP-обработчик и не продлевает его резервирование автоматически. Задания с истёкшим резервированием могут быть зарезервированы повторно; старое резервирование не может подтвердить выполнение задания, которое уже обрабатывает новый процесс.

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

Совместная фиксация данных предметной области и задания

$database->connection()->transactional(function ($connection) use ($queue): void {
    $connection->insert('reports', ['status' => 'pending']);
    $queue->push('reports.generate', ['report_id' => (int) $connection->lastInsertId()]);
});

Обе операции должны использовать одно и то же внедрённое подключение Database. Исключение откатывает их вместе. Внешние HTTP-вызовы, доставка почты и отдельные базы данных находятся за пределами этой транзакции.

Планирование заданий

use Elang\Queue\Schedule;

$schedule = $app->container->get(Schedule::class);
$schedule->everyMinute('reports.minute', 'reports.generate', ['report_id' => 42]);
$schedule->dailyAt('reports.daily', '02:00', 'reports.generate', ['report_id' => 43]);

Запускайте php elang schedule:run раз в минуту через cron. Время задаётся в UTC. Общий уникальный ключ запуска в базе данных не позволяет двум процессам планировщика поставить в очередь одно расписание с тем же ID в одну и ту же минуту. Это не препятствует наложению долгого задания на следующий запуск по расписанию. Если такое наложение недопустимо, добавьте блокировку приложения. Пропущенные минуты не восполняются.

Продолжите изучение с событий в реальном времени и архитектуры крупных приложений.

Нужна помощь?

Проверьте руководство по решению проблем, найдите термин в глоссарий, или пройдите полноценный проект доски задач.

Поиск по документации Elang

Начните вводить, чтобы найти следующий шаг.