Laravel - отчет о работе как неудачный (даже если он завершается правильно)

Я использую последнюю версию Homestead. У меня также установлен Laravel Horizon. Я использую Redis в качестве драйвера очереди. Laravel - это версия 5.6, это новая установка.

Происходит то, что все мои рабочие места терпят неудачу (хотя работа завершается правильно).

Я запускаю задание из командной строки с помощью специальной команды:

vagrant@homestead:~/myapp$ artisan crawl:start
vagrant@homestead:~/myapp$ <-- No CLI errors after running

приложение / Консоль / Команда / crawl.php

<?php

namespace MyApp\Console\Commands;

use Illuminate\Console\Command;
use MyApp\Jobs\Crawl;

class crawl extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'crawl:start';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Start long running job.';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {


        Crawl::dispatch();

    }

}

app / Jobs / Crawl.php

<?php

namespace MyApp\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class Crawl implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * The number of seconds the job can run before timing out.
     *
     * @var int
     */
    public $timeout = 3600;

    /**
     * The number of times the job may be attempted.
     *
     * @var int
     */
    public $tries = 1;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct()
    {

    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {


        $crawl = new Crawl();
        $crawl->start();


    }
}

app / Crawl.php

<?php
namespace MyApp;

class Crawl
{

    public function start()
    {

        ini_set('memory_limit','256M');
        set_time_limit(3600);

        echo "Started."; 
        sleep(30);
        echo "Exited.";
        exit(); 

    }
}

worker.log

[2018-03-21 10:14:27][1] Processing: MyApp\Jobs\Crawl
Started.
Exited.
[2018-03-21 10:15:59][1] Processing: MyApp\Jobs\Crawl
[2018-03-21 10:15:59][1] Failed:     MyApp\Jobs\Crawl

Из подробностей неудачной работы Horizon

Failed At    18-03-21 10:15:59
Error        Illuminate\Queue\MaxAttemptsExceededException:
             MyApp\Jobs\Crawl has been attempted too many 
             times or run too long. The job may have previously 
             timed out. in /home/vagrant/app/vendor/laravel
             /framework/src/Illuminate/Queue/Worker.php:396

laravel-worker.conf

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /home/vagrant/myapp/artisan queue:work --sleep=3 --tries=1 --timeout=3600
autostart=true
autorestart=true
user=vagrant
numprocs=1
redirect_stderr=true
stdout_logfile=/home/vagrant/myapp/worker.log

конфигурация / queue.php

'redis' => [
    'driver' => 'redis',
    'connection' => 'default',
    'queue' => 'default',
    'retry_after' => 90,
    'block_for' => null,
],

.env

QUEUE_DRIVER=redis

Синопсис

Глядя на свой worker.log, я вижу, что результат моего класса сработал:

Started.
Exited.

Но работа считается неудавшейся. Почему? Странно, но также в worker.log он говорит Processing дважды для одного задания:

[2018-03-21 10:15:59][1] Processing: MyApp\Jobs\Crawl
[2018-03-21 10:15:59][1] Failed:     MyApp\Jobs\Crawl

Любая помощь приветствуется!

ОБНОВИТЬ

Удаление exit() устранило проблему - это странно, поскольку в руководстве по PHP сказано, что вы можете использовать exit() для выхода из программы "в обычном режиме":

https://secure.php.net/manual/en/function.exit.php
<?php

//exit program normally
exit;
exit();
exit(0);

person beingalex    schedule 21.03.2018    source источник


Ответы (1)


Удаление exit() устранило проблему - это странно, поскольку в руководстве по PHP сказано, что вы можете использовать exit() для выхода из программы «в обычном» режиме.

Это верно для обычных программ, но задание в очереди в Laravel не следует тому же жизненному циклу.

Когда система очередей обрабатывает задание, это задание выполняется в существующем рабочем процессе очереди. В частности, работник очереди извлекает данные задания из серверной части, а затем вызывает метод handle() задания. Когда этот метод возвращается, работник очереди запускает некоторый код для завершения задания.

Если мы выходим из задания, вызывая exit(), die() или вызывая фатальную ошибку, PHP также останавливает рабочий процесс, выполняющий задание, поэтому система очередей никогда не завершает жизненный цикл задания, и задание никогда не помечается как «завершенное».

Нам не нужно явно выходить из работы. Если мы хотим завершить работу раньше, мы можем просто вернуться из метода handle():

public function handle() 
{
    // ...some code...

    if ($exitEarly) {
        return;
    }

    // ...more code...
}

Laravel также включает черту InteractsWithQueue, которая предоставляет API, который позволяет заданию управлять собой. В этом случае мы можем вызвать метод delete() из задания, которое демонстрирует эту черту:

public function handle()
{
    if ($exitEarly) {
        $this->delete();
    }
}

Но работа считается неудавшейся. Почему? Как ни странно, также в worker.log написано: «Обработка дважды для одного задания».

Как описано выше, задание не удалось успешно завершить, потому что мы вызвали exit(), поэтому система очередей послушно попыталась повторить задание.

person Cy Rossignol    schedule 12.04.2018