Run scheduler using cron method in Laravel - laravel

I have an expires_at column in one of my models and I want to run a scheduler based on the timestamp of that.
I tried the following code :
$collection = Foo::first();
$schedule->call( function() {
// Do Something
})->cron( \Carbon\Carbon::parse( $collection->expires_at )->format( 'i h d m' ) . ' *' );
But when I run php artisan schedule:run at the expire date I get No scheduled commands are ready to run.

Instead of calling function you can do that by command. Make command for that cron job and than you can specify that schdeuler in schedule method of kernel.php
schedule->command('command Name')
->cron( \Carbon\Carbon::parse( $collection->expires_at )->format( 'i h d m' ) . ' *' );
Hope this helps :)

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.

Laravel: Send slack notification after a scheduled task finished

I need to schedule a few tasks on an application built using Laravel and I would like to send a slack notification after those tasks are finished with the output.
Laravel provides an "after" hook (https://laravel.com/docs/5.8/scheduling#task-hooks) so I can do something like this:
$schedule->command('mycommand')
->daily()
->after(function () {
// How can I access the command's name and output from here?
});
I've tried with $this->output but $this points to App\Console\Kernel and it says Undefined property: App\Console\Kernel::$output. I've also tried to pass a parameter to the closure, but I think I need to specify a type, but I have no idea and the documentation is not very clear.
Anyone has any idea on how to do this?
Thanks in advance!
Assuming you have this in your command
$this->info('hello');
In your kernel, you can send the output to a temporary file and then read the file and send it
/** #var \Illuminate\Console\Scheduling\Event $command */
$command = $schedule->command('mycommand')
->daily()
->sendOutputTo('storage/app/logs.txt');
$command->after(function () use ($command) {
\Log::debug([$command->command, $command->output]);
\Log::debug(file_get_contents($command->output));
});
You will get
[2019-10-11 13:03:38] local.DEBUG: array (
0 => '\'/usr/bin/php7.3\' \'artisan\' command:name',
1 => 'storage/app/logs.txt',
)
[2019-10-11 13:03:38] local.DEBUG: hello
Maybe it would be the time to re-open this proposal https://github.com/laravel/ideas/issues/122#issuecomment-228215251
What kind of output does your command generate? is it command line or is just a variable you're trying to pass to the after()?
Alternativly in your handle() method of the command you can call the desired command after all the code has been excuted, you can even pass a parameter to the command.
You can do that by using Artisan
Artisan::call('*command_name_here*');

Laravel: detect if running migrations

I have setup some event listeners in which I would like to detect if I'm runnnig database migrations or a normal request/command.
Is there some way of knowing this? Global flag? Environment?
Thanks in advance.
You can check if the console is being used with App::runningInConsole() ... that might be sufficient depending on how you are running the migrations.
Update:
OK, after doing some more digging, it looks like you can hack your way to the info you need using the follow example:
if(app()->runningInConsole()) {
// we are running in the console
$argv = \Request::server('argv', null);
// :$ php artisan migrate:refresh -v
//
// gives:
//
// $argv = array (
// 0 => 'artisan',
// 1 => 'migrate:refresh',
// 2 => '-v',
// )
if($argv[0] == 'artisan' && \Illuminate\Support\Str::contains($argv[1],'migrate')) {
// we are running the artisan migrate command
}
}
Source: How to get the current console command in Laravel
Actually, Laravel fires several events while running migrations:
Illuminate\Database\Events\MigrationsStarted : A batch of migrations is about to be executed.
Illuminate\Database\Events\MigrationsEnded : A batch of migrations has finished executing.
Illuminate\Database\Events\MigrationStarted : A single migration is about to be executed.
Illuminate\Database\Events\MigrationEnded : A single migration has finished executing.
You can utilize this to do anything you want. For example:
// change default Log channel when running migrations
Event::listen(function (MigrationsStarted $event) {
config()->set('logging.default', 'migration');
});
In your case, you can set a key in your app config files like app.running_migrations and set it to true in the event listener.

Scheduled task with parameter 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.

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