首页 > 解决方案 > 如何使用 Laravel 批量插入避免 504 网关超时?

问题描述

连接可以有 1,000 - 10,000 个项目传递给它。尝试点击此控制器时,我不断收到 504,我已将其从个人更改Create为集体Insert(一个查询),但如果连接数高于 1000,它仍然会抛出 504。

如何改进此代码以不引发 504?我真的不想花 60 秒的时间。

耗时最长的函数是storeConnections

<?php

declare(strict_types = 1);

namespace App\Http\Controllers\Api\Cache;

use App\Http\Controllers\Controller;
use App\Http\Requests\StoreCacheItemRequest;
use App\Models\CacheConnection;
use App\Models\CacheItem;
use App\Models\CacheMedia;
use App\Models\QueueItem;
use App\Models\QueueItemFailed;
use Illuminate\Http\Request;

class StoreController extends Controller
{
    public function __invoke(StoreCacheItemRequest $request)
    {
        if (CacheItem::where('item', $request->get('item'))->exists())
        {
            return response()->json([
                'error' => 'Cache item ' . $request->get('item') . ' already exists.'
            ], 500);
        }

        $cache = CacheItem::create([
            'item' => $request->get('item'),
            'name' => $request->get('name'),
            'picture' => $request->get('picture'),
            'description' => $request->get('description'),
            'connection_count' => $request->get('connection_count'),
            'is_private' => $request->get('is_private'),
            'has_snap' => $request->get('has_snap', false),
            'additional_data' => $request->get('additional_data'),
            'type_id' => $request->get('type_id'),
        ]);

        if ($request->has('connections')) {
            $this->storeConnections($request->get('connections'), $cache->id);
        }

        if ($request->has('pictures')) {
            $this->storeMedia($request->get('pictures'), $cache->id);
        }
    }

    private function storeConnections($connections, $cacheId)
    {
        $connectionData = [];
        foreach ($connections as $item) {
            $queryData[] = [
                'cache_id' => $cacheId,
                'item' => $item
            ];
        }

        CacheConnection::insert($connectionData);

        $queueData = [];

        foreach ($queryData as $item) {
            if (!QueueItem::where('item', $item)->exists() &&
                !QueueItemFailed::where('item', $item)->exists() &&
                !CacheItem::where('item', $item)->exists())
            {
                $queueData[] = [
                    'item' => $item,
                ];
            }
        }

        Queue::insert($queueData);
    }

    private function storeMedia($media, $cacheId)
    {
        foreach ($media as $item) {
            CacheMedia::create([
                'cache_id' => $cacheId,
                'item' => $item
            ]);
        }
    }
}

标签: phpmysql

解决方案


推荐阅读