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
Related
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 am writing Laravel json api using MySQL. What I am trying to do, is whenever user creates record, I want to perform some operation on this record every 24 hours, until some changes are made by admin on this record. So averagely this job will be repeated 10-15 times. this is my 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 App\Http\Models\Orders\RoadOrder;
class RoadOrderEprirationHandler implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* #return void
*/
protected $order_id;
public function __construct($order_id)
{
$this->order_id = $order_id;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$order = RoadOrder::findOrFail($this->order_id);
//do some tasks and if I need to run this cycle again :
$roadOrderEprirationHandler = new RoadOrderEprirationHandler($order->id);
$roadOrderEprirationHandler->dispatch($order->id)->delay(now()->addHours(24));
}
}
So as you can see, I initiate job after previous job was finished if admin didn't modified record and I need to run cycle again. after several cycles, I won't run job again, so it will be finished.
My question:
Is some problem in this implementation? maybe I am doing something wrong or maybe there may occur some type of memory leak (because I create job inside job again and again). I can write this but I need to be sure that this implementation doesn't leads to some type of bugs or errors.
Why don't create a separate table in your DB for that purpose?
You can keep order_ids with status (checked by admin / not checked). Or just put new order_id there and delete it after admin check. So you will only use your jobs to see is there any unchecked ids. Or some kind of that.
I think this approach is more predictable and less buggy.
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!
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.