Процесс очереди Laravel получает тайм-аут

Я запускаю команду, которая должна запускать импорт Laravel Excel, но через некоторое время она истощается. Я использую куски, и раньше это работало, но теперь я изо всех сил пытаюсь заставить это работать. Это группа файлов, расположенных в папке внутри файловой системы.

Это команда, которую я запускаю с ремесленником:

public function handle()
    {
        //
        $directory = 'pv';
        $files = Storage::allFiles($directory);
        \Log::info('Process started.');
        $start = microtime(true);
        ini_set('max_execution_time', 600);
        foreach($files as $file)
        {
            $fname = basename($file);
            \Log::info('Processing',[$fname]);
            $arr = explode(" ", $fname);
            $day = substr($arr[2], 0, 10);
            $date = Carbon::parse($day);
            Excel::queueImport(new POSImport($date), $file);
        }
        $time = microtime(true) - $start;
        $me = '[email protected]';
        $msg = 'Process finished in '. $time.' secs.';
        Mail::to($me)->queue(new TasksFinished($msg));
        $this->call('calcular:previos', [
        '--queue' => 'default'
        ]);
    }

Выбивается из памяти.

Это импорт.

<?php

namespace App\Imports;

use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Pos;
use App\Device;
use \Datetime;

class POSImport implements ToCollection, WithHeadingRow, WithChunkReading, ShouldQueue
{


   public $tries = 3;

   function __construct(Datetime $date) {
       $this->date = $date;
   }

   /**
    * Importa datos de la planilla de puntos vigentes de Banco Estado.
     * 
     * Actúa sobre Device (equipos) y POS 
     * 
    * @param Collection $rows
    */

    public function collection(Collection $rows)
    {
        //
        ini_set('max_execution_time', 600);
        foreach($rows as $row)
        {
            // crea o modifica POS

            if(!isset($row['marca'])) {
                return null;
            }
            // Busca el POS (lugar) en la base
            $pos = Pos::where('id', $row['pos'])->first();
            // si no hay un "pos" registrado lo crea
            if(!$pos) {
                $pos = new Pos;
                $pos->id = $row['pos'];
                $pos->vigente = ($row['estado'] == 'VIGENTE' ? true : false);
                $pos->save();
            } else {
                $pos->vigente = ($row['estado'] == 'VIGENTE' ? true : false);
                $pos->save();
            }
            // limpia serial de ceros a la izquierda
            $serial = ltrim($row['serie_equipo'], '0');
            // busca serial en la base de datos
            $device = Device::where('serial', $serial)
                    ->where('fecha_recepcion', '<', $this->date)
                    ->where('customer_id', 1)
                    ->orderBy('fecha_recepcion', 'asc')
                    ->first();

            if($device && $device->pos_id != $row['pos'] && $device->fecha_instalacion != $this->date){
                // busca el dispositivo anterior

                $device->pos_id = $pos->id;
                $device->fecha_instalacion = $this->date;
                $device->save();

                $device->pos()->attach($pos);
            } 
        }

    }

    public function chunkSize(): int {
        return 2000;
    }

}

Как видите, я использую WithChunkReading и ShouldQueue. Когда я запускал этот процесс в прошлом, он просто обрабатывал фрагменты, но теперь в очереди отображается множество записей QueueImport.

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

Я надеюсь, что вы можете помочь мне с этим.

Ошибка в команде:

Symfony\Component\Debug\Exception\FatalErrorException  : Allowed memory size of 536870912 bytes exhausted (tried to allocate 175747072 bytes)

  at C:\laragon\www\reportes\vendor\laravel\framework\src\Illuminate\Queue\Queue.php:138
    134|
    135|         return array_merge($payload, [
    136|             'data' => [
    137|                 'commandName' => get_class($job),
  > 138|                 'command' => serialize(clone $job),
    139|             ],
    140|         ]);
    141|     }
    142|


   Whoops\Exception\ErrorException  : Allowed memory size of 536870912 bytes exhausted (tried to allocate 175747072 bytes)

  at C:\laragon\www\reportes\vendor\laravel\framework\src\Illuminate\Queue\Queue.php:138
    134|
    135|         return array_merge($payload, [
    136|             'data' => [
    137|                 'commandName' => get_class($job),
  > 138|                 'command' => serialize(clone $job),
    139|             ],
    140|         ]);
    141|     }
    142|

Это много данных, поэтому я использую куски и очереди, но у меня все еще есть эта проблема.


person ffuentes    schedule 18.03.2019    source источник


Ответы (1)


class POSImport implements ShouldQueue
{
    /**
     * The number of seconds the job can run before timing out.
     *
     * @var int
     */
    public $timeout = 120;
}

Кроме того, если вы хотите, чтобы ваш обработчик очереди увеличил время ожидания, вы можете использовать флаг --timeout (я думаю, что по умолчанию он равен 30 секундам):

php artisan queue:work --timeout=300


Я не уверен в этом, но также может работать:

$this->call('calcular:previos', [
    '--queue' => 'default',
    '--timeout' => '300'
]);

person senty    schedule 18.03.2019
comment
Проблема в том, что он также будет исчерпан для размера памяти, но раньше этого не было, даже если сами файлы не изменились. [2019-03-18 14:56:59][312] Обработано: Maatwebsite\Excel\Jobs\QueueImport [2019-03-18 14:57:04][313] Обработано: Maatwebsite\Excel\Jobs\ReadChunk [2019 -03-18 14:57:56][313] Обработано: Maatwebsite\Excel\Jobs\ReadChunk [2019-03-18 14:58:00][314] Обработано: Maatwebsite\Excel\Jobs\QueueImport, тогда как раньше только readchunk был выполнен. - person ffuentes; 18.03.2019
comment
Whoops\Exception\ErrorException : разрешенный размер памяти 536870912 байт исчерпан (попытка выделить 175747072 байт) для команды и Symfony\Component\Process\Exception\ProcessTimedOutException : процесс C:\laragon\bin\php\php-7.2.11 -Win32-VC15-x64\php.exe artisan queue:work --once --queue=default --delay=0 --memory=512 --sleep=3 --tries=3 превысил тайм-аут в 60 секунд. в очереди - person ffuentes; 18.03.2019
comment
Хм, я подозреваю, что это может быть проблема с fastcgi - в вашей конфигурации nginx внутри location ~ \.php$ { } добавьте fastcgi_read_timeout 3600; внизу - person senty; 18.03.2019
comment
Я использую апач. Теперь фрагменты считываются, но команда исчерпает память. - person ffuentes; 18.03.2019
comment
ini_set('memory_limit', '512M'); Можешь попробовать? Это связано с распределением памяти php - person senty; 18.03.2019
comment
Я не понимаю, зачем уменьшать лимит памяти? - person ffuentes; 18.03.2019
comment
Потому что ошибка Allowed memory size of 536870912 bytes exhausted (tried to allocate 175747072 bytes) - разрешенный размер памяти вашего php меньше, чем необходимо. Попробуйте сначала с ini_set('memory_limit', '-1');, что позволяет php использовать неограниченные ресурсы, но вам нужно настроить его вместо использования -1 - person senty; 18.03.2019
comment
Тогда мне придется увеличить память, я думаю, не уменьшить ее. - person ffuentes; 18.03.2019
comment
Вы имеете в виду флаг --memory в вашей команде queue:work? Я думаю, что это просто ограничитель, чтобы убить работу, а не для разрешенного размера памяти вашего php. Вам нужно отредактировать ваш php.ini, но я не уверен, какой именно (php-cli или php-fpm). - person senty; 18.03.2019