Laravel Scheduled queue:work not working automatically need to manual trigger - laravel

I have a very large cron job that need to be carry out, but server cannot handle it due to memory leaks, so i follow the suggestion to use laravel Queue, and because i can't always run php artisan queue:work, so i wrote a scheduled queue command that trigger every 5 minutes, but the queue not working unless i manual trigger it on server.
Here is my command for queue:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class EnsureQueueListenerIsRunning extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'queue:checkup';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Ensure that the queue listener is running.';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
//
$this->startQueueListener();
if ( ! $this->isQueueListenerRunning()) {
$this->comment('Queue listener is being started.');
$pid = $this->startQueueListener();
$this->saveQueueListenerPID($pid);
}
$this->comment('Queue listener is running.');
}
/**
* Check if the queue listener is running.
*
* #return bool
*/
private function isQueueListenerRunning()
{
if ( ! $pid = $this->getLastQueueListenerPID()) {
return false;
}
$process = exec("ps -p $pid -opid=,cmd=");
//$processIsQueueListener = str_contains($process, 'queue:listen'); // 5.1
$processIsQueueListener = ! empty($process); // 5.6 - see comments
return $processIsQueueListener;
}
/**
* Get any existing queue listener PID.
*
* #return bool|string
*/
private function getLastQueueListenerPID()
{
if ( ! file_exists(__DIR__ . '/queue.pid')) {
return false;
}
return file_get_contents(__DIR__ . '/queue.pid');
}
/**
* Save the queue listener PID to a file.
*
* #param $pid
*
* #return void
*/
private function saveQueueListenerPID($pid)
{
file_put_contents(__DIR__ . '/queue.pid', $pid);
}
/**
* Start the queue listener.
*
* #return int
*/
private function startQueueListener()
{
//$command = 'php-cli ' . base_path() . '/artisan queue:listen --timeout=60 --sleep=5 --tries=3 > /dev/null & echo $!'; // 5.1
$command = 'php artisan queue:work --timeout=60 --sleep=5 --tries=3 > /dev/null & echo $!'; // 5.6 - see comments
$pid = exec($command);
return $pid;
}
}
Here is the kernel:
$schedule->command('queue:checkup')->everyFiveMinutes();
What should i do to make it work?

if you want to set the crone job to run automatically without initiating using command.**
go to your terminal: and run this command
crontab -e
This will open server crontab file, paste this code inside, save it and exit
* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1

Related

Schedule to copy all id of Table A to Table B for weekly and insert a date to Table B Laravel

What I'm intending to do is to make a task scheduling for weekly, which is to copy all of id from table route_schedule and insert into table route_schedule_details as FK, which then will insert the date of the weeks. This is how the route_schedule_details schema:
Schema::create('route_scheduler_details', function (Blueprint $table) {
$table->id();
$table->dateTime('schedule_date')->nullable();
$table->unsignedBigInteger('route_scheduler_mstr_id')->nullable()->index('FK_route_scheduler_details_route_scheduler_mstr');
$table->foreign(['route_scheduler_mstr_id'], 'FK_route_scheduler_details_route_scheduler_mstr')->references(['id'])->on('route_scheduler_mstr')->onDelete('cascade');
});
I never used task scheduling before so I'm little bit under-knowledged here. Read in Laravel docs, I have to add the schedule in App/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
$data = [];
$copies = RouteSchedulerMSTR::select('id')->get();
foreach($copies as $copy){
//I'm not sure what to do in here
}
})->weekly(1, '1:00');
}
Firstly, you need to create command because above your code can't test work or not :
php artisan make:command RouteSchedulerWeekly
<?php
namespace App\Console\Commands;
use App\Models\RouteSchedulerMSTR;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class RouteSchedulerWeekly extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'routeschedule:weekly';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Run route scheduler weekly';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return int
*/
public function handle()
{
$copies = RouteSchedulerMSTR::select('id')->get();
foreach($copies as $copy){
DB::table('route_scheduler_details')->insert([
'data' => now(),
'route_scheduler_mstr_id' => $copy
]);
$this->info('Route scheduler inserting...');
}
$this->info('Done!');
}
}
Then you can test your code insert or not :
php artisan routeschedule:weekly
if you wanted function is correct, you can run by cronjob with 2 options
Direct run command with cron
crontab -e
and add below script to crontab file on your server:
0 1 * * 6 cd /var/www/your-project && php artisan routeschedule:weekly >> /dev/null 2>&1
You can test crontab script here
In Windows use Task Scheduler
OR
Run with schedule:run
Add your command in Kernel
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('routeschedule:weekly')->weekly(1, '1:00');
}
}
and add below script to crontab file on your server:
* * * * * cd /var/www/your-project && php artisan schedule:run >> /dev/null 2>&1
here * * * * * is every minute
Conclusion: I recommend option 1 that will run once in a week on your server. The option 2 also run once in a week your command but schedule:run running every minute

How to Run Laravel Scheduler on Google Cloud

I am trying to run Laravel Scheduler in Google Cloud.
In my command, I have this
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\User;
use Carbon\Carbon;
class ChangeRole extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'command:update';
/**
* The console command description.
*
* #var string
*/
protected $description = 'This Changes Stuffs';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
//
$users = User::where('trialExpires', '<=', Carbon::now())->get();
foreach ($users as $user) {
$user->type= 'subscriber';
$user->save();
}
}
}
I have done this in my Kernel
protected $commands = [
//
'App\Console\Commands\ChangeRole',
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('command:update')
->daily();
}
In my cron.yaml file
cron:
- description: "daily job"
url: '* * * * * cd /project_id && php artisan command:update >> /dev/null 2>&1'
schedule: every 24 hours
retry_parameters:
min_backoff_seconds: 2.5
max_doublings: 5
timezone: Europe/Madrid
When I ran gcloud app deploy cron.yaml
I got this error
ERROR: (gcloud.app.deploy) An error occurred while parsing file: [C:\xampp1\newlibri\cron.yaml]
Unable to assign value '* * * * * cd /starlit-advice-260914 && php artisan command:update >> /dev/null 2>&1' to attribute 'url':
Value '* * * * * cd /starlit-advice-260914 && php artisan command:update >> /dev/null 2>&1' for url does not match expression '^(?:^/.*$)$'
in "C:\xampp1\newlibri\cron.yaml", line 3, column 8
I don't know what I did wrong.
When I run PHP artisan command:update. The scheduler work just fine. But I am unable to replicate on Google Cloud
I have been able to fix the error.
I have to set the URL to a get request in my application.
cron:
- description: "daily summary job"
url: /api/checksub
schedule: every 24 hours
retry_parameters:
min_backoff_seconds: 2.5
max_doublings: 5
timezone: Europe/Madrid
In my controller, I have this
public function checksub() {
$users = User::where('trialExpires', '<=', Carbon::now())->update(['role'=> 'subscriber']);
));
}
It doesn't need to setup Laravel Scheduler. Just call the get result of the URL
You might want to use the default implementation for these scheduler tasks. Basically what you do is setup a CRON task which runs the scheduler function every minute, and let the PHP code decide whether to run particular tasks.
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
This will run your app\Console\Kernel.php::schedule() function every minute, in which you can then define your tasks like:
// Example function which removes users older than a year.
$schedule->call(function () {
User::query()
->where('created_at', '<', Carbon::now()->subYear())
->delete();
})->hourly();
See https://laravel.com/docs/7.x/scheduling

cron job with laravel to send emails to user

please help me i'm trying to make a cron job on my server to send email to user
i created a command like that :
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'contract:end';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Send an email to user about the end of a contract';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
$contracts = Contract::where('end_date', Carbon::parse(today())->toDateString())->get();
foreach ($contracts as $contract) {
Mail::to(Setting::first()->value('email'))->send(new ContractEmail($contract));
}
}
and in my kernel.php i added the following code :
* The Artisan commands provided by your application.
*
* #var array
*/
protected $commands = [
//
Commands\ContractEnd::class,
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('contract:end')
->everyMinute();
}
/**
* Register the commands for the application.
*
* #return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
and on my server i run the following command to run the cron job :
cd /archive/artisan && schedule:run >> /dev/null 2>&1
but it didn't send any email , can anyone help me as it's my first time using it ?
Because your command in your server is wrong you need to specify the correct path which will contain/home/your username/your website folder/artisan like this
/usr/local/bin/php /home/your user name which you can get in from job page/archive/artisan schedule:run 1>> /dev/null 2>&1

Laravel Scheduling not firing command

I have a simple set up a command for Scheduling that is firing on a cron call
The artisan command works fine yet nothing happens when Scheduling
The Schedule
protected function schedule(Schedule $schedule)
{
$schedule->command('prices:pricing')
->everyMinute();
}
The Task
protected $signature = 'prices:pricing';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Gets Pricing data and stores in DB';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
Log::debug('An informational message.');
}
}
The cron
* * * * * www-data cd /var/www/api && php artisan schedule:run >> /dev/null 2>&1
Also I have tried with running
php artisan queue:listen

"Best way" to run Laravel queue listen

Currently I'm working on a project where I queue emails to be send. However I wonder what would be the "best way" to run the queue listener. Right now I only know about the nohup way.
However, by using nohup it feels like the queue listener is no part of the application anymore. It's like using the scheduler to make your cronjobs more part of the application.
Are there any other ways to listen the queue and what would be your preference?
Here's what I wrote to achieve this:
app/Console/Commands/QueueProcessListener.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class QueueProcessListener extends Command
{
/**
* The name of the command/process we want to monitor. This string will be used both to check to see if the process
* is currently running and to spawn it (The arguments are appended to it).
*
* #var string
*/
protected $command = 'php artisan queue:listen';
/**
* The arguments to pass to the process when spawning it.
*
* #var string
*/
protected $arguments = '--tries=3';
/**
* The signature of the console command. We use the signature when running it through Artisan: php artisan $signature
*
* #var string
*/
protected $signature = 'queue-process-listener';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Monitor the queue listener process to ensure it is always running.';
/**
* Create a new command instance.
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
if (!$this->isProcessRunning($this->command)) {
$this->info("Starting queue listener.");
$this->executeShellCommand($this->command, $this->arguments, true);
} else {
$this->info("Queue listener is running.");
}
}
/**
* Execute a shell command, with the provided arguments, and optionally in the background. Commands that are not run
* in the background will return their output/response.
*
* #param $command
* #param string $arguments
* #param bool $background
* #return string
*/
public function executeShellCommand($command, $arguments = '', $background = false)
{
$command = trim($command);
if (!is_string($command) || empty($command)) {
return null;
}
$arguments = trim($arguments);
$cmd = trim($command . ' ' . $arguments) . ($background ? ' > /dev/null 2>/dev/null &' : '');
return shell_exec($cmd);
}
/**
* Check if a process is running using pgrep.
*
* #param $process
* #return bool
*/
public function isProcessRunning($process)
{
$output = $this->executeShellCommand('pgrep -f "' . $process . '"');
return !empty(trim($output));
}
}
app/Console/Kernel.php
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* #var array
*/
protected $commands = [
Commands\QueueProcessListener::class
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
// Schedule my process listener to run every 5 minutes.
$schedule->command('queue-process-listener')->everyFiveMinutes();
}
}
The documentation tells you exactly how to achieve this:
https://laravel.com/docs/5.3/queues#supervisor-configuration
I'm not sure what you mean by it not being "part of the application". Crons and background worker processes are a standard part of any scale server architecture. There's nothing wrong with using them.
You also should really avoid doing what Jonathon's answer suggests, which is basically writing your own supervisord in php. What if your server reboots? There are battle-tested solutions for this problem, that have been developed and supported by the linux community for a long time now--you should really use them.

Resources