Laravel получает ошибку memory_limit при создании папки из базы данных

Я хочу создавать папки на основе user_id внутри /laravel/public/file/FolderUserXXX. Если у меня есть 1000 записей пользователей в базе данных, я хочу создать 1000 папок внутри пути (мне нужно создать эти папки, потому что мой сервер отключается, а папки исчезают).

Я создал задание для его выполнения, и я пробовал его локально с небольшими данными (работает), но в процессе производства я всегда получаю ошибку Allowed memory size of xxxxxxxxxxxxx bytes exhausted (пытался выделить xxxxxxxx байтов). Я добавляю memory_limit до 4 ГБ в php.ini, но проблема все еще возникает.

Вот мой код в app/Console/Commands

сценарий:

Задание createfolder для пользователя с status >= 3 и remark_restore - это null. При каждом успешном создании remark_restore будет изменяться на 1. Я пытался ограничить 1 данными на задание и запускать каждую минуту, но все равно получаю ошибку.

Но если я изменю memory_limit на -1 только для запуска этого задания, а затем верну его обратно к предыдущему значению, будет ли какое-либо влияние в будущем для моей сети?

Есть предложения о том, как предотвратить ошибку memory_limit?

public function handle()
{
    try {
        ini_set('max_execution_time', 300000);
        ini_set('memory_limit','4096M');
        $take = 1;

        $make_folder = User::where('status', '>=', '3')->wherenull('remark_restore')->limit($take)->get();

        foreach ($make_folder as $make_folder) {
            $path = public_path().'/file/'.$make_folder->id;

            if (!(file_exists($path))) {
                $data = User::where('id', $make_folder->id)->update(array('remark_restore' => '1' ));
                File::makeDirectory($path, $mode = 0777, true, true);
            }
        }

        $count = User::where('status', '>=', '3')->wherenull('remark_restore')->count();

        echo 'Pending : '.$count;
    }
    catch (\Exception $e) {
        \Log::warning($e);
    }
}

Попробуйте задержать создание папки внутри вашей функции foreach (). Пример добавления сна (5)

Jesus Erwin Suarez 31.03.2021 08:05

и попробуйте добавить ограничение на запрос, например limit (10) на запрос.

Jesus Erwin Suarez 31.03.2021 08:06
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
2
38
1

Ответы 1

Ладно, вы путаете ...

Правильный подход здесь - отправлять задание для каждой папки вместо того, чтобы выполнять одно задание для каждого создания.

Итак, у вас должна быть работа типа CreateFolderForUser и в ней что-то вроде:

class CreateFolderForUser
{
    protected $user;

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

    public function handle()
    {
        try {
            $path = public_path("/file/{$this->user->id}");

            if (!(file_exists($path))) {
                File::makeDirectory($path, 0777, true, true);

                $this->user->remark_restore = 1;
                $this->user->save();
            }
        }
        catch (\Exception $e) {
            \Log::warning($e);
        }
    }
}

Видите, я удалил все, что касается итерации пользователей, вам просто нужно выполнить эту работу, а именно «Создать папку для этого пользователя», ничего больше ...

Также обратите внимание, что я переместил обновление remark_restoreпосле, создав каталог, потому что в вашем предыдущем коде, если создание не удалось, вы уже обновили remark_restore пользователя до 1, но это неверно, у вас была ошибка ...


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

public function dispatchUserFolderCreation()
{
    $take = 1000;
    $users = User::where('status', '>=', '3')
        ->whereNull('remark_restore')
        ->limit($take)
        ->chunk(100, function (Collection $users) {
            foreach ($users as $user) {
                dispatch(new CreateFolderForUser($user));
            }
        });
}

Вы можете динамически передавать желаемый $take, если используете команду, поэтому по умолчанию используется 1000, но если вы хотите меньше или больше (не отправляйте 10000, делайте это партиями 2000, не больше), вы можете это сделать.

Другие вопросы по теме