Laravel Schedule

dakata__92

Super Moderator
Колеги, пуснах си една крон задачка, всяка минутка да върти и експортва огромен лог ако има заявка за това. Проблема, е че се припокриват виканията на функцията и съответно сложих кеш, но това не е решение.
Код:
$schedule->command('export:csv')->everyMinute()->runInBackground()
Код:
public function run()
    {
        $data = [];
        $export = new Export;
        $items = $export::where('status', '=', 0)->get();
        foreach ($items as $key => $item) {
            $key = 'cron_'.$item->id.'_'.md5($item->json);
            if (cache()->has($key)) {
                Debug::set('Task ('.$key.') has already started!');
                continue;
            }
            cache()->put($key, $item->id, 3600);
            try {
                switch ($item->type) {
                    case 1:
                        $data['log_1'][] = $this->logOne($export, $item);
                        break;
                    case 2:
                        $data['log_2'][] = $this->logTwo($export, $item);
                        break;
                }
            } catch (\Throwable $e) {
                continue;
            }
        }
        Debug::set($data);
    }

Мисля да сложа withoutOverlapping() но при това положение вероятно ще е необходимо в run да сложа while(true) {}:

Код:
public function run()
    {
		while(true) {
			$data = [];
			$export = new Export;
			$items = $export::where('status', '=', 0)->get();
			foreach ($items as $key => $item) {
				$key = 'cron_'.$item->id.'_'.md5($item->json);
				if (cache()->has($key)) {
					Debug::set('Task ('.$key.') has already started!');
					continue;
				}
				cache()->put($key, $item->id, 3600);
				try {
					switch ($item->type) {
						case 1:
							$data['log_1'][] = $this->logOne($export, $item);
							break;
						case 2:
							$data['log_2'][] = $this->logTwo($export, $item);
							break;
					}
				} catch (\Throwable $e) {
					continue;
				}
			}
			Debug::set($data);
		}
    }
Какво бихте ми предложили за да не се преизвикват вече стартирали заявки със статус 0 и още не обновили статуса на 1? Старите кронове ги въртях с bash команди и нямах проблем с преизвикване, защото правех безкраен цикъл и на практика слушах нонстоп една инстанция на крона и ако процеса е спрял вдигам нова.
 
dakata__92 каза:
Revelation каза:
В такъв случай ти трябва опашка, а не крон.
Коя функционалност предлагаш да погледна?


https://laravel.com/docs/8.x/queues

Идеята е, вместо всяка минута да проверяваш дали някой е пожелал експортването на този лог (предполагам е в крон, защото инак не му стига време/памет и в cli има по-малко рестрикции), когато някой поиска големия експорт, да го пушнеш в опашка (queue).
 
И понеже не искаш да се overlap-ват: https://laravel.com/docs/8.x/queues#preventing-job-overlaps

П.П. Иначе трябва да се занимаваш да слагаш флагове или да изчислиш колко време е бил най-дългия експорт и да нагодиш крона по него. Но ако това не може да се изчисли понеже времената могат да зависят от много фактори, пак ще получиш overlap.

За това най-добре е да слагаш на опашката.
 
С междинен статус в базата с данни стана работата. Отделно ползвам нещата така:
$schedule->command('export')->everyMinute()->withoutOverlapping()->runInBackground();
 
Тази схема изглежда много интересна
 

Горе