Laravel — Отчет о задании как сбой (даже если он корректно завершается)

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

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

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

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

приложение / Console / Command / 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();

}

}

приложение / Работа / 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();


}
}

Приложение / 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,
],

.окр

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);

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()Таким образом, система очередей покорно попыталась повторить задание.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]