Laravel - обработка большого количества небольших записей данных в одном запросе с общим временем выполнения 2+ минуты - PullRequest
0 голосов
/ 02 марта 2020

TLDR: у меня есть 150 секунд l oop для запуска, инициированного HTTP-запросом, мне нужно asyn c, так как запрос будет d ie из-за времени до его завершения - Laravel Появляются очереди для обработки большого отдельного импорта, а не тысячи маленьких - так кто-нибудь знает, как это сделать?

Более длинная версия:

Я пытаюсь импортировать большую электронную таблицу в мою MySQL базы данных, но время выполнения превышает 60 секунд, поэтому время ожидания запроса истекло. Мой код перебирает данные, создавая строки в базе данных:

Это метод в контроллере - «ProjectController», главное, что есть очень длинный l oop, поскольку для обработки требуется так много данных и хранить

public function bulkStore(Request $request)
    {
        $allProjects = $request->all();

        $properties = Property::where('client_id', 1)->get();
        $propertiesArray = [];

        foreach($properties as $property)
        {
            $propertiesArray[$property->name] = $property->id;
        }

        foreach($allProjects as $project)
        {
            $project = json_decode(json_encode($project), true);

            $project_id = Project::create([
                'client_id' => 1,
                'reference' => $project['Reference'],
                'name' => $project['Project Name'],
                'description' => null,
                'created_at' => Carbon::now()->format('Y-m-d H:i:s'),
                'updated_at' => Carbon::now()->format('Y-m-d H:i:s')

            ])->id;



            foreach($project as $property => $value)
            {
                if(!in_array($property, array('Reference', 'Project Name')))
                {

                    $property_id = $propertiesArray[$property];

                    $value = json_encode($value);

                    DB::table('property_values')->insert([
                        'project_id' => $project_id,
                        'property_id' => $property_id,
                        'data' => $value,
                        'created_at' => Carbon::now()->format('Y-m-d H:i:s'),
                        'updated_at' => Carbon::now()->format('Y-m-d H:i:s')
                    ]);
                }
            }
        }
    }

Я не уверен, куда поместить этот код и как обработать запрос, чтобы он выполнялся в фоновом режиме после быстрой проверки 200: нормально, клиент получает ответ.

Любая помощь очень ценится - извиняюсь, если это l oop отвратительно - я довольно новичок в программировании.

Ответы [ 2 ]

0 голосов
/ 02 марта 2020

Вы можете переместить логи c в задание.

В вашем контроллере
use App\Jobs\ProcessProperties;

public function bulkStore(Request $request)
  {
    $allProjects = $request->all();

    $properties = Property::where('client_id', 1)->get();

    ProcessProperties::dispatch($properties);
  }
app/Jobs/ProcessProperties.php
<?php

namespace App\Jobs;

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

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

  protected $properties;

  public function __construct($properties)
  {
    $this->properties = $properties;
  }

  public function handle()
  {
    $propertiesArray = [];

    foreach($this->properties as $property)
    {
      $propertiesArray[$property->name] = $property->id;
    }

    foreach($allProjects as $project)
    {
      $project = json_decode(json_encode($project), true);

      $project_id = Project::create([
        'client_id' => 1,
        'reference' => $project['Reference'],
        'name' => $project['Project Name'],
        'description' => null,
        'created_at' => Carbon::now()->format('Y-m-d H:i:s'),
        'updated_at' => Carbon::now()->format('Y-m-d H:i:s')
      ])->id;

      foreach($project as $property => $value)
      {
        if(!in_array($property, array('Reference', 'Project Name')))
        {
          $property_id = $propertiesArray[$property];

          $value = json_encode($value);

          DB::table('property_values')->insert([
            'project_id' => $project_id,
            'property_id' => $property_id,
            'data' => $value,
            'created_at' => Carbon::now()->format('Y-m-d H:i:s'),
            'updated_at' => Carbon::now()->format('Y-m-d H:i:s')
          ]);
        }
      }
    }

    // You can emit and event here to be notified when the job completes
  }
}

Тогда все о запуске работника очереди с php artisan queue:work.

0 голосов
/ 02 марта 2020

Создание красноречивых моделей - тяжелая часть, я думаю. Вы можете просто сохранить данные во временном json файле и вернуть 200 OK.

Storage::disk('your_temp_disk')->put('import.json', json_encode($project));

Затем поставить в очередь задание:

ImportProjects::dispatch($path_to_the_import_json);

Затем забрать файл в задании ImportProjects создайте свои модели и, наконец, удалите временный файл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...