Laravel Ошибка экспорта в очередь Excel - PullRequest
0 голосов
/ 21 января 2020

У меня были большие проблемы с получением пакета Laravel Excel для экспорта большого количества данных. Мне нужно экспортировать около 80-100 тыс. Строк, поэтому я реализовал экспорт из очереди , как указано в документации . Он отлично работает, когда я экспортирую меньшее количество строк, но когда я пытаюсь сделать 60-80 тыс. Строк, каждый раз происходит сбой. Во время обработки заданий я наблюдаю созданный временный файл и вижу, что размер файла увеличивается. Я также наблюдаю за заданиями в базе данных (я использую драйвер очереди базы данных) и вижу, что задания завершаются на некоторое время. Кажется, что задания занимают все больше времени, пока работа не сработает. Я не понимаю, почему первые несколько заданий выполняются быстро, а затем они начинают занимать все больше и больше времени.

Я использую supervisor для управления очередью, поэтому вот мой конфиг для этого:

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/site/artisan queue:work --sleep=3 --tries=3 --timeout=120 --queue=exports,default
autostart=true
autorestart=true
user=www-data
numprocs=8
redirect_stderr=true
stdout_logfile=/var/log/supervisor/worker.log
loglevel=debug

А потом мой контроллер для создания экспорта

(new NewExport($client, $year))->queue('public/exports/' . $name)->allOnQueue('exports')->chain([
    new NotifyUserOfCompletedExport($request->user(), $name),
]);

Я использую:

Laravel 5.8, PHP 7.2, Postgresql 10.10

Я должен также упомянуть, что я немного поиграл с размером чанка, но в конце я всегда сталкивался с одной и той же проблемой. Я пробовал куски размером 500, 2000, 10000, но не повезло.

В таблице failed_jobs исключение составляет MaxAttemptsExceededException, хотя у меня также есть исключения для InvalidArgumentException File '/path/to/temp/file' does not exist. Я не совсем уверен, что еще делать. Я думаю, я мог бы сделать это так, чтобы не было времени ожидания, но похоже, что это только вызовет больше проблем. Любая помощь будет оценена.

РЕДАКТИРОВАТЬ

Вот содержание моего класса экспорта:

class NewExport implements FromQuery, WithHeadings, WithMapping, WithStrictNullComparison
{

    public function __construct($client, $year)
    {
        $this->year = $year;
        $this->client = $client;
    }

    public function query()
    {
        $data = $this->getDataQuery();

        return $data ;
    }

    public function headings(): array
    {
        $columns = [
            //....
        ];

        return $columns;
    }

    public function map($row): array
    {
        $mapping = [];
        foreach($row as $key => $value) {
            if(is_bool($value)) {
                if($value) {
                    $mapping[$key] = "Yes";
                } else {
                    $mapping[$key] = "No";
                }
            }else{
                $mapping[$key] = $value;
            }
        }
        return $mapping;
    }

    private function getDataQuery()
    {
        $query = \DB::table('my_table')->orderBy('my_field');

        return $query;
    }

Класс NotifyUserOfCompletedExport просто создает работу, чтобы отправить по электронной почте вошел в систему пользователя, что экспорт завершен со ссылкой для его загрузки.

class NotifyUserOfCompletedExport implements ShouldQueue
{
    use Queueable, SerializesModels;

    public $user;
    public $filename;

    public function __construct(User $user, $filename)
    {
        $this->user = $user;
        $this->filename = $filename;
    }

    public function handle()
    {
        // This just sends the email
        $this->user->notify(new ExportReady($this->filename, $this->user));
    }
}

РЕДАКТИРОВАТЬ 2:

Итак, я прочитал этот пост , и я убедился, что со временем на моем сервере просто не хватает памяти. Это приводит к ошибке MaxAttemptsExceededException. Я добавил больше памяти на сервер, и я все еще получаю InvalidArgumentException File '/path/to/temp/file' does not exist после выполнения заданий. Это даже более странно, потому что я вижу, что / path / to / temp / file на самом деле существует . Так что я понятия не имею, что здесь происходит, но это супер расстраивает.

...