I have a job to send emails when the user registers in the application.
SendWelcomeEmail.php
<?php
namespace App\Jobs;
use App\Jobs\Job;
use App\User;
use Illuminate\Contracts\Mail\Mailer;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class SendWelcomeEmail extends Job implements ShouldQueue
{
use InteractsWithQueue, SerializesModels;
protected $user;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Execute the job.
*
* #return void
*/
public function handle(Mailer $mailer)
{
$user = &$this->user;
$message = sprintf('Hello %s', $user->name);
$mailer->raw($message, function ($m) use ($user){
$m->from('lucas.nuck#gmail.com', 'Lucas Lopes');
$m->to($user->email, $user->name);
});
}
}
I would like to create a job to execute the php artisan queue: work command every minute to send the emails that are in the queue.
Easiest way would be to set up Supervisor.
https://laravel.com/docs/5.4/queues#supervisor-configuration, it will automatically restart your queue:work process if it fails.
To solve the confusion for you:
In app/Console/Kernel.php file, inside the schedule function you would add a command that you want to be ran at a specific interval. An example would be :
$schedule->command('SendFailedLoginsReport')->weekly()->mondays()->at('03:00');
On your server, you can add your cron like this
* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
This Cron will call the Laravel command scheduler every minute
You are wanting to run the queue daemon, not run a command. You need to do this within your server environment, not using laravels scheduled commands.
You could use something like Linux's screen to place your command in.
This will consinuiously poll your queue server for new jobs, then process them.
Related
I currently registered php artisan schedule:run in cronjob in cpanel and the schedule method is:
protected function schedule(Schedule $schedule)
{
$schedule->command('queue:work --stop-when-empty')
->cron('* * * * *')
->withoutOverlapping(5);
}
But for my purpose it is necessary to run the jobs immediately,
How can I run php artisan queue:work immediately after a job added to queue(jobs table) and not after one minute?
For Laravel > 7.x We can dispatch anonymosly
use App\Mail\WelcomeMessage;
use Illuminate\Support\Facades\Mail;
dispatch(function () {
Mail::to('taylor#laravel.com')->send(new WelcomeMessage);
})->afterResponse();
The WelcomeMessage should implement/use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
For Laravel 6.x
Instead of dispatching a job class to the queue, you may also dispatch a Closure. This is great for quick, simple tasks that need to be executed outside of the current request cycle:
$podcast = App\Podcast::find(1);
dispatch(function () use ($podcast) {
$podcast->publish();
});
for more you can read laravel docs https://laravel.com/docs/7.x/queues
the solution is to call queue:work on destruct() method of each class that I want to run it's job immediately.
use Illuminate\Support\Facades\Artisan;
class ProductShopObserver implements ShouldQueue
{
public function __destruct()
{
Artisan::call('queue:work --stop-when-empty');
}
}
I am implementing Queue JOBS, in my Laravel Project for the first time. But I am facing some difficulties on it, as after php artisan queue:work, noting is showing on the terminal.
Let Me describe, the procedure I have tried.
My Controller Function, from where I am trying to fire the Job Queue:
use App\Jobs\InitiateRecharge;
/
/*** Other Codes are here....
/
public function testQueueJob(){
InitiateRecharge::dispatch(1)->onQueue('initrecharge');
return 1;
}
My JOB Queue Class:
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class InitiateRecharge implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $reportid;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($reportid)
{
$this->reportid = $reportid;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
sleep(10);
\Log::info('hello....');
}
}
I have also migrated the jobs table, and rows are also getting inserted on that.
It's is not giving any error, but the Job expected output is also not coming .. and in the terminal noting getting changed.
Please, anyone, help me
Thank You in advance :)
try php artisan queue:listen --tries=1
I use spatie media library for one of my project. requirement is when uploaded image status is approved then generate conversions of that particular image. So, i write code for that in My Model is:
public function registerMediaConversions(Media $media = null)
{
$listingStatus = ListingStatus::where('type', Listing::ITEM_TYPE_PHOTOS)->where('item_id', $media->id)->where('status', self::STATUS_APPROVED)->whereNotNull('review_by')->first();
if ($listingStatus)
$this->registerBaseConversions(true);
}
and when image getting approved then i dispatch job for run command.
$this->dispatch(new GenerateMediaCollection($mediaId));
Job:
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Log;
class GenerateMediaCollection implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $mediaId;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($mediaId)
{
$this->mediaId = $mediaId;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
Log::info('generate Media collection');
exec('php artisan medialibrary:regenerate --ids='.$this->mediaId);
}
}
so, in Local all is working perfectly but in server, job is processed but conversions not added.
if i run command in server from terminal then it is working.
So, what i have to do for this issue?
TIA.
Try adding --force to arguments. I.e. make it
exec('php artisan medialibrary:regenerate --ids='.$this->mediaId --force')
I'm using database driver to queue my jobs.
I need to call an artisan command from a queued Job and when the Job has finished I need to remove it from the queue.
This is my controller's code where I add the job in the queue
dispatch((new SendNewsletter())->onQueue('newsletter'));
This is my queued Job
<?php
namespace App\Jobs;
use App\Console\Commands\Newsletter;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class SendNewsletter implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct()
{
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
app()->make(Newsletter::class)->handle();
}
}
The artisan command I need to call is App\Console\Commands\Newsletter
and when the Job ends, this should remove it from the queue.
This is AppServiceProvider class
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot() {
Queue::after(function ($event) {
if ($event->job->queue == 'newsletter') {
$event->job->delete();
}
});
}
The Job is added correctly to the database queue and when I run php artisan queue:work the job is called multiple times endless.
seems that Queue::after's callback is never called.
any idea what am I missing ?
Probably your job fails and it is added to queue trying to finsh the work correctly. Try calling the command in your job like this
\Artisan::call('your:command');
Instead of:
app()->make(Newsletter::class)->handle();
Where "your:command" is the command name, that you gave in the command class:
protected $signature = 'email:send {user}';
I have such function in my trait:
public function cupPlayMatch(Season $season, $round_id)
{
foreach($season->cups as $cup)
{
$this->cupPlay($cup, $round_id);
}
}
And second cup isstarting playing when first cup finished. How I can start playing all my cups simultaneous?
For the most part, PHP is "synchronous", that means that you theoretically can't make "simultaneous calls" to any function.
However, some workarounds exist to make this work.
PHP is a script language. So when you launch this in your console:
php -r "echo 'Hello World';"
A PHP process is launched, and anything that happen in this process is executed synchronously.
So the solution here, is to launch various PHP processes in order to be able to run functions simultaneously.
Imagine an SQL table where you put all the functions that you want to execute simultaneously. You could then run 10 php processes that would actually work "at the same time".
Laravel provides a solution to this problem out of the box. And as #Anton Gildebrand mentioned it in the comments, it's called "Queues".
You can find the documentation here: https://laravel.com/docs/5.5/queues
The laravel way of doing it, is to create "jobs". Each Job represents a function that you want to execute. Here, your Job would be cupPlay.
Here is the basic example of a job copy pasted from the documentation:
<?php
namespace App\Jobs;
use App\Podcast;
use App\AudioProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class ProcessPodcast implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $podcast;
/**
* Create a new job instance.
*
* #param Podcast $podcast
* #return void
*/
public function __construct(Podcast $podcast)
{
$this->podcast = $podcast;
}
/**
* Execute the job.
*
* #param AudioProcessor $processor
* #return void
*/
public function handle(AudioProcessor $processor)
{
// Process uploaded podcast...
}
}
When you'll have configured your worker driver to run your queues, you'll just need to launch:
php artisan queue:work --queue=high,default
from the command line and it will execute your tasks.
And you can execute as many workers as you want, depending on your needs...
I hope this helps!