Scheduled task with parameter laravel - laravel

in Laravel 5.6 i have a controller that invokes a command through a Process component.
The command run fine, is about a compression of a folder with the name the user gives.
$command = 'tar -czvf '.$nameFile.' storage/images/';
$process = new Process($command);
$process->setTimeout(1800);
$process->run();
I need to schedule that job 3 times a day. I saw task scheduling with file app/Console/Kernel.php; the problem is to execute the process with the file name the user gives.
How can i programm a Schedule task in this situation?
Thanks

Assume you run the schedule tasks three times a day, per each user input. You can create a eloquent model for such purpose, says ProcessTask, and save the required data in Controller:
ProcessTask::create(['user_id' => $userId, 'name_file' => $nameFile]);
Then, you can make scheduling task as:
$schedule->call(function () {
$tasks = ProcessTask::all();
foreach ($tasks as $task) {
$command = 'tar -czvf '.$task->name_file.' storage/images/';
....
}
})->hourly()
->when(function() { return date('H') % 8 == 0; }) // run tasks at 00:00, 08:00, 16:00
->name('processTask')
->withoutOverlapping();
If the scheduling tasks are time-consuming, the best practice is to dispatch tasks to queue and let workers consume it.

Related

InvalidArgumentException : Invalid CRON field value 30 at position 4

I tried To run this command php artisan schedule:run on laravel project I got this error
InvalidArgumentException : Invalid CRON field value 30 at position 4
at /var/www/vendor/dragonmantank/cron-expression/src/Cron/CronExpression.php:155
151| */
152| public function setPart($position, $value)
153| {
154| if (!$this->fieldFactory->getField($position)->validate($value)) {
> 155| throw new InvalidArgumentException(
156| 'Invalid CRON field value ' . $value . ' at position ' . $position
157| );
158| }
159|
this is command on my Kernel
protected function schedule(Schedule $schedule)
{
// Schedule to delete old messages every old days
$schedule -> command(DeleteOldMessages::class, ['days' => config('marketplace.days_old_messages')])
->days(config('marketplace.days_old_messages'));
// Make the command for releasing purchases runs each X days
$schedule -> command(ReleasePurchasesCommand::class, ['days' => config('marketplace.days_old_purchases')])
->days(config('marketplace.days_old_purchases'));
// Run completing command for purchases every defined number of days
$schedule -> command(CompletePurchaseCommand::class) -> days(config('marketplace.days_complete'));
}
I dont know what issue is
Thanks in advance for any help.
The scheduler ->days() function is expecting an array of days of the week on which the task should run. For instance ([1,3,5]) meaning run on Monday,Wednesday and Friday)
I assume with values of 20 and 30, you are expecting the tasks to run at a specified interval. This is not possible with cron based scheduling.
What you probably want is to run the tasks every day and within the task, determine if any records exceed the specified limits.

How to call `catch` closure for every failed job in job batches Laravel 8

Laravel 8 introduced Job Batching, which allows to execute jobs in batches and perform actions on batch completion and failure. When a job within batch fails, the catch callback is executed and the whole batch is marked as "canceled" according to the documentation. In case you don't want the batch to cancel (on the first failure) you can append the method allowFailures() while dispatching the batch:
$batch = Bus::batch([
// ...
])->then(function (Batch $batch) {
// All jobs completed successfully...
})->catch(function (Batch $batch, Throwable $e) {
// First batch job failure detected...
// TODO: call this for every failed job
})->allowFailures()->dispatch();
It works as expected, however I wonder whether it's possible to call catch closure for every failed job? (at this case with allowFailures)
You can use number of attemtps in Jobs for finding failed job
if ($this->attempts() > 1) {
// your code
}

Laravel dispatching Queues at set time

I am currently dispatching queued jobs to send API Events instantly, in busy times these queued jobs need to be held until overnight when the API is less busy, how can I hold these queued jobs or schedule them to only run from 01:00am the following day.
the Queued Job call currently looks like:
EliQueueIdentity::dispatch($EliIdentity->id)->onQueue('eli');
there are other jobs on the same queue, all of which will need to be held in busy times
Use delay to run job at a certain time.
EliQueueIdentity::dispatch($EliIdentity->id)
->onQueue('eli')
->delay($this->scheduleDate());
Helper for calculating the time, handling a edge case between 00:00 to 01:00, where it would delay it a whole day. While not specified how to handle busy, made an pseudo example you can implement.
private function scheduleDate()
{
$now = Carbon::now();
if (! $this->busy()) {
return $now;
}
// check for edge case of 00:00:00 to 01
if ($now->hour <= 1) {
$now->setTime(1, 0, 0);
return $now;
}
return Carbon::tomorrow()->addHour();
}
You can use delayed dispatching (see https://laravel.com/docs/6.x/queues#delayed-dispatching):
// Run it 10 minutes later:
EliQueueIdentity::dispatch($EliIdentity->id)->onQueue('eli')->delay(
now()->addMinutes(10)
);
Or pass another carbon instance like:
// Run it at the end of the current week (i believe this is sunday 23:59, havent checked).
->delay(Carbon::now()->endOfWeek());
// Or run it at february second 2020 at 00:00.
->delay(Carbon::createFromFormat('Y-m-d', '2020-02-02'));
You get the picture.

Laravel multiple tasks simultaneously

I need to process several image files from a directory (S3 directory), the process is to read the filename (id and type) that is stored in the filename (001_4856_0-P-0-A_.jpg), this file is stored in the moment is invoked the process (im using cron and schedule, it works great) the objetive of the process is to store the info into a database.
I have the process working, it works great but my problem is the number of files that is in the directory, because every second adds a lot more files to the directory, the time spent in the process is about 0.19 sec for file, but the amount of files is huge, about 15,000 per minute is added, so i think a multiple simultaneous process (about 10 - 40 times) of the same original process can do the job.
I need some advice or idea,
First to know how to launch multiple process at the same time of one original process.
Second how to get only the non selected filenames bcause the process takes the filenames with:
$recibidos = Storage::disk('s3recibidos');
if(count($recibidos) <= 0)
{
$lognofile = ['Archivos' => 'No hay archivos para procesar'];
$orderLog->info('ImagesLog', $lognofile);
}else{
$files = $recibidos->files();
if(Image::count() == 0)
{
$last_record = 1;
} else{
$last_record = Image::latest('id')->pluck('id')->first()+1;
}
$i=$last_record;
$fotos_sin_info = 0;
foreach($files as $file)
{
$datos = explode('_',$file);
$tipos = str_replace('-','',$datos[2]);
Image::create([
'client_id' => $datos[0],
'tipo' => $tipos,
]);
$recibidos->move($file,'/procesar/'.$i.'.jpg');
$i++;
}
but i dont figured out how to retrieve only the non selected.
Thanks for your comments.
Using multi-threaded programming in php is possible and has been discussed on so How can one use multi threading in PHP applications.
However this is generally not the most obvious choice for standard applications. A solution for your situation will depend on the exact use-case.
Did you consider a solution using queues?
https://laravel.com/docs/5.6/queues
Or the scheduler?
https://laravel.com/docs/5.6/scheduling

Laravel Cron not auto run (Windows)

I use Cron (https://github.com/liebig/cron) for Laravel 4 to run specific task in specific time
I have this code in my Global.php
Event::listen('cron.collectJobs', function() {
Cron::add('example1', '* * * * *', function() {
$trip = new TripReminder();
$trip->checkDateAndSendEmail();
});
Cron::setRunInterval(1);
$report = Cron::run();
print_r ($report);
});
=>This Code use to Send an email to the customers in every minute (just demo and check)
in cmd, i run this command "php artisan cron:run"
It can run well, the email was sent also, but, it only run 1 times.
I don't know what i'm missing.
Please help !
Thank you !

Resources