{{TOC}} {{DOCVER 4.0=0da300f6445bec5a70d007f503834fce957b065b 16.10.2014 5:19:26, 4.1=efd541a0b218b1c6aafb73f0051c18ed150e3c24 25.05.2014 6:21:03, 4.2=d7b13440c003218ed79e9d508706eca01990122f 4.12.2014 5:01:15}} == Настройка == В Laravel, компонент Queue предоставляет единое API для различных сервисов очередей. Очереди позволяют вам отложить выполнение времязатратной задачи, такой как отправка e-mail, на более позднее время, таким образом на порядок ускоряя загрузку (генерацию) страницы. Настройки очередей хранятся в файле %%(t)app/config/queue.php%%. В нём вы найдёте настройки для драйверов-связей, которые поставляются вместе с фреймворком: ((http://kr.github.com/beanstalkd Beanstalkd)), ((http://iron.io/ IronMQ)), ((http://aws.amazon.com/sqs Amazon SQS)), ((http://redis.io Redis)), а также синхронный драйвер (для локального использования). Упомянутые выше драйвера имеют следующие зависимости: * **Beanstalkd:** %%(t)pda/pheanstalk ~2.0%% * **Amazon SQS:** %%(t)aws/aws-sdk-php%% * **IronMQ:** %%(t)iron-io/iron_mq%% == Основы использования == **Добавление новой задачи в очередь** %% Queue::push('SendEmail', array('message' => $message)); %% **Регистрация обработчика задачи** Первый аргумент метода %%Queue::push()%% - имя класса, который должен использоваться для обработки задачи. Второй аргумент - массив параметров, которые будут переданы обработчику. Обработчик задачи должен быть зарегистрирован так: %% class SendEmail { public function fire($job, $data) { // } } %% Заметьте, что %%fire()%% - единственный обязательный метод этого класса; он получает экземпляр объект %%Job%% и массив данных, переданных при добавлении задачи в очередь. **Задача с произвольным методом-обработчиком** Если вы хотите использовать какой-то другой метод вместо %%(t)fire%% - передайте его имя при добавлении задачи: %% Queue::push('SendEmail@send', array('message' => $message)); %% %%(DOCNEW 4.1=efd541a0b218b1c6aafb73f0051c18ed150e3c24 25.05.2014 6:21:03) **Задание очереди для задачи** Вы можете задать очередь (//queue// или //tube//) в которую следует посылать задачу: ~%% Queue::push('SendEmail@send', array('message' => $message), 'emails'); ~%% **Передача одинаковых данных в несколько задач** Если вам надо передать одинаковые данные в несколько задач в очереди, вы можете использовать метод %%Queue::bulk()%%: ~%% Queue::bulk(array('SendEmail', 'NotifyUser'), $payload); ~%% **Задержка выполнения задачи** Иногда вам может понадобиться задержать выполнение задачи в очереди. Например, вы захотите поместить в очередь задачу, которая отправляет пользователю e-mail через 15 минут после регистрации. Вы можете добиться этого, используя метод %%Queue::later()%%: ~%% $date = Carbon::now()->addMinutes(15); Queue::later($date, 'SendEmail@send', array('message' => $message)); ~%% В этом примере мы используем библиотеку для работы со временем ((GIT:../briannesbitt/Carbon Carbon)), чтобы указать необходимое время задержки для задачи. Другой вариант - передать необходимое число секунд для задержки. %% **Удаление выполненной задачи** Как только вы закончили обработку задачи она должна быть удалена из очереди - это можно сделать методом %%delete()%% объекта %%Job%%: %% public function fire($job, $data) { // Обработка задачи... $job->delete(); } %% **Помещение задачи обратно в очередь** Если вы хотите поместить задачу обратно в очередь - используйте метод %%release()%%: %% public function fire($job, $data) { // Обработка задачи... $job->release(); } %% Вы также можете указать число секунд, после которого задача будет помещена обратно: %% $job->release(5); %% **Получение числа попыток запуска задания** Если во время обработки задания возникнет исключение, задание будет помещено обратно в очередь. Вы можете получить число сделанных попыток запуска задания методом %%attempts()%%: %% if ($job->attempts() > 3) { // } %% **Получение идентификатора задачи** %% $job->getJobId(); %% == Добавление замыканий == Вы можете помещать в очередь и функции-замыкания. Это очень удобно для простых, быстрых задач, выполняющихся в очереди. **Добавление замыкания в очередь** %% Queue::push(function ($job) use ($id) { Account::delete($id); $job->delete(); }); %% .(alert) Вместо того, чтобы делать объекты доступными для замыканий очередей через директиву %%use%%, передавайте первичные ключи и повторно извлекайте связанные модели из вашей задачи в очереди. Это часто позволяет избежать неожиданного поведения при сериализации. .(alert) Константы %%__DIR__%% и %%__FILE__%% не должны использоваться в замыканиях. При использовании ((#push push-очередей)) //Iron.io// будьте особенно внимательны при добавлении замыканий. Конечная точка выполнения, получающая ваше сообщение, должна проверить входящую последовательность-ключ, чтобы удостовериться, что запрос действительно исходит от //Iron.io//. Например, ваша конечная push-точка может иметь адрес вида %%(t)https://yourapp.com/queue/receive?token=SecretToken%% - где значение **token** можно проверять перед собственно обработкой задачи. == Работа сервера приёма очереди == Laravel включает в себя задание ((docs/v4/artisan Artisan)), которое будет выполнять новые задачи по мере их поступления. Вы можете запустить его командой %%(t) queue:listen%%. **Запуск сервера приёма** %%(sh) php artisan queue:listen %% Вы также можете указать, какое именно соединение должно прослушиваться: %%(sh) php artisan queue:listen connection %% Заметьте, что когда это задание запущено оно будет продолжать работать, пока вы не остановите его вручную. Вы можете использовать монитор процессов, такой как ((http://supervisord.org/ Supervisor)), чтобы удостовериться, что задание продолжает работать. %%(DOCNEW 4.1=efd541a0b218b1c6aafb73f0051c18ed150e3c24 25.05.2014 6:21:03) Вы можете передать команде %%(sh)listen%% список подключений к очереди через запятую, чтобы задать приоритеты для очереди: %%(sh) php artisan queue:listen --queue=high,low ~%% В этом примере задачи из подключения **high-connection** всегда будут обрабатывать перед задачами из **low-connection**. %% **Указание времени на выполнение задачи** Кроме этого вы можете указать число секунд, в течение которых будет выполняться каждая задача: %%(sh) php artisan queue:listen --timeout=60 %% **Указание перерыва между задачами** Также вы можете задать число секунд ожидания перед проверкой наличия новых задач в очереди: %%(sh) php artisan queue:listen --sleep=5 %% Обратите внимание, что очередь "засыпает" только тогда, когда в ней нет задач. Если задачи есть, очередь будет продолжать обрабатывать их без перерыва. **Обработка только первой задачи в очереди** Для обработки только первой задачи можно использовать команду %%(t)queue:work%%: %%(sh) php artisan queue:work %% %%(DOCNEW 4.2=d7b13440c003218ed79e9d508706eca01990122f 4.12.2014 5:01:15) == Демон-обработчик очереди == Команда %%(sh)queue:work%% также имеет опцию %%(sh)--daemon%% для того, чтобы обработчик принудительно продолжал обрабатывать задачи без необходимости повторной загрузки фреймворка. Это приводит к значительному снижению использования CPU по сравнению с командой %%(sh)queue:listen%%, но добавляет сложности из-за необходимости в избавлении от очередей текущих задач во время вашего развёртывания. Для запуска обработчика очереди в режиме демона используйте флаг %%(sh)--daemon%%: %%(sh) php artisan queue:work connection --daemon php artisan queue:work connection --daemon --sleep=3 php artisan queue:work connection --daemon --sleep=3 --tries=3 ~%% Как видите, команда %%(sh)queue:work%% поддерживает те же самые опции, что и команда %%(sh)queue:listen%%. Для просмотра всех доступных опций используйте команду %%(sh)php artisan help queue:work%%. === Развёртывание с помощью демонов-обработчиков очереди === Простейший способ развернуть приложение, используя обработчики очереди, - перевести приложение в режим техобслуживания в начале развёртывания. Это можно сделать с помощью команды %%(sh)php artisan down%%. Когда приложение перейдет в режим обслуживания, Laravel не будет принимать новые задачи из очереди, но продолжит обработку имеющихся задач. Самый лёгкий способ перезапуска ваших обработчиков - включить следующую команду в ваш скрипт для развёртывания: %%(sh) php artisan queue:restart ~%% Эта команда сообщит всем обработчикам очереди о необходимости перезапуска после завершения обработки их текущих задач. .(alert) Эта команда полагается на систему кэша для планирования перезапуска. По умолчанию APCu не работает для терминальных команд. Если вы используете APCu, добавьте %%(conf)apc.enable_cli=1%% в свою конфигурацию для APCu. === Написание кода для демонов-обработчиков очереди === Демоны-обработчики очереди не перезапускают фреймворк перед обработкой каждой задачи. Поэтому нужно быть аккуратным при освобождении любых "тяжёлых" ресурсов до того, как закончится выполнение вашей задачи. Например, если вы обрабатываете изображение с помощью библиотеки GD, то после завершения обработки вам необходимо освобождать память с помощью %%imagedestroy%% . Так же, ваше соединение с БД может быть потеряно, когда оно используется демоном долгое время. Вы можете использовать метод %%DB::reconnect()%%, для обеспечения "свежего" соединения. %% == ((#push)) Push-очереди == Push-очереди дают вам доступ ко всем мощным возможностям, предоставляемым подсистемой очередей Laravel 4 без запуска серверов или фоновых программ. На текущий момент push-очереди поддерживает только драйвер //Iron.io//. Перед тем, как начать, создайте аккаунт и впишите его данные в %%(t)app/config/queue.php%%. **Регистрация подписчика push-очереди** После этого вы можете использовать ((docs/v4/artisan Artisan))-команду %%(t)queue:subscribe%% для регистрации URL конечной точки, которая будет получать добавляемые в очередь задачи: %%(sh) php artisan queue:subscribe queue_name http://foo.com/queue/receive %% Теперь, когда вы войдёте в ваш профиль //Iron.io//, то увидите новую push-очередь и её URL подписки. Вы можете подписать любое число URL на одну очередь. Дальше создайте маршрут для вашей конечной точки %%(t)queue/receive%% и пусть он возвращает результат вызова метода %%Queue::marshal()%%: %% Route::post('queue/receive', function () { return Queue::marshal(); }); %% Этот метод позаботится о вызове нужного класса-обработчика задачи. Для помещения задач в push-очередь просто используйте всё тот же метод %%Queue::push()%%, который работает и для обычных очередей. %%(DOCNEW 4.1=efd541a0b218b1c6aafb73f0051c18ed150e3c24 25.05.2014 6:21:03) == Проваленные задачи == Не всегда всё идёт по плану, иногда ваши задачи в очереди будут заканчиваться ошибкой. Не волнуйтесь, такое с каждым случается! В Laravel есть удобный способ указать максимальное количество попыток выполнения задачи. После превышения этого количества попыток, задача будет добавлена в таблицу %%(t)failed_jobs%%. Название таблицы проваленных задач может быть настроено в файле %%(t)app/config/queue.php%%. Для создания миграции для таблицы %%(t)failed_jobs%%, можно использовать команду %%(sh)queue:failed-table%%: %%(sh) php artisan queue:failed-table ~%% Указать максимальное количества попыток выполнения задачи можно с помощью ключа %%(sh)--tries%% команды %%(sh)queue:listen%%: %%(sh) php artisan queue:listen connection-name --tries=3 ~%% Если вы хотите зарегистрировать событие, которое будет вызываться при ошибке выполнения задачи, можете использовать метод %%Queue::failing()%%. Это событие - отличная возможность оповестить вашу команду через e-mail или ((www.hipchat.com HipChat)). ~%% Queue::failing(function($connection, $job, $data) { // }); ~%% Чтобы просмотреть все проваленные задачи, можно использовать ((docs/v4/artisan Artisan))-команду %%(sh)queue:failed%%: %%(sh) php artisan queue:failed ~%% Эта команда выведет список задач с их ID, подключением, очередью и временем ошибки. ID задачи можно использовать для повторной попытки её выполнения. Например, для повторной попытки выполнения задачи с ID = 5 надо выполнить такую команду: %%(sh) php artisan queue:retry 5 ~%% Если вы хотите удалить проваленную задачу, используйте команду %%(sh)queue:forget%%: %%(sh) php artisan queue:forget 5 ~%% Для удаления всех проваленных задач используйте команду %%(sh)queue:flush%%: %%(sh) php artisan queue:flush ~%% %%