Lumen prevent duplicate job in a queue - php

Using lumen 8.2.3 I am only trying to dispatch a unique job to a queue. In app/Console/Kernel I have sent a schedule to $schedule->job(new myJob(), 'high')->everyMinute(); this runs every minutes.
In the job itself I have added the ShouldBeUnique interface class in myJob class I even added
public function uniqueId() {
return $this->process->id();
}
when my cron job runs for php artisan schedule:run, this is still creating multiple jobs in the queue causing my 3 workers to pick up both jobs at the same time and causing issues.
https://laravel.com/docs/8.x/queues#unique-jobs clearly says
"Sometimes, you may want to ensure that only one instance of a
specific job is on the queue at any point in time. You may do so by
implementing the ShouldBeUnique interface on your job class. This
interface does not require you to define any additional methods on
your class:"
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Throwable;
class myJob implements ShouldQueue, ShouldBeUnique
{
use InteractsWithQueue, Queueable, SerializesModels;
private $process;
public function __construct($process){
$this->process=$process;
}
public function uniqueId() {
return $this->process->id();
}
public function handle()
{
//some code here
}
public function failed(Throwable $exception)
{
// Send user notification of failure, etc...
}
}
Is the no way to prevent this? thank you

The code provided barely reflects what you are writing; there's no job at all.
The declaration should look like this:
class SomeJob implements ShouldQueue, ShouldBeUnique
{
use InteractsWithQueue, Queueable, Dispatchable;
...
}

odd how this got fixed but what I did was change the version from 8.2.4 to 8.3.4 and shouldBeUnique work looks like a bug was introduced in 8.3.4

Related

how to run the jobs queue immediately after a job added to queue in laravel?

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');
}
}

Laravel-5.8: Not getting output on Queue Jobs

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

Laravel Jobs and Queues not working as expected

I'm creating an application which generates a video. This is a quite intensive function and takes a few minutes to generate. So I want to create a async process for this. After some research I've read about Jobs and Queues in Laravel.
But now my jobs don't get inserted in the jobs table. I can't find out what I've done wrong.
My function which starts the job:
public function generate() {
$id = Auth::user()->id;
GenerateJob::dispatch($id);
}
My Job
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Auth;
class GenerateJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct($dossierId)
{
$this->dossierId = $dossierId;
}
public function handle()
{
sleep(5);
}
}
.ENV QUEUE_DRIVER=database
I did run php artisan clear:config but nothing seems to help.
Nothing I try seems to work. The jobs table remains empty and the job is executed synchronously instead of asynchronously. What am I missing here?
After hours of debugging I finally found a solution to my problem. Adding ->onConnection('database'); to GenerateJob::dispatch($dossier_id); solved it all..
I wish I could say why this was necessary, but I have no clue since I already put that in my .env file. Hope this helps for someone else in this situation. :-)

Queueing mails in Laravel

I would like to send mail to user after creating account on my website and I would like to use queues to send them. I'm using PHP Laravel framework.
My controller handles the request after clicking on "Create account":
class LoginController extends Controller
{
...
public function register(Request $request) {
...
$mail = (new RegisterRequest($user))->onConnection("database")->onQueue("emailsQueue");
Mail::queue($mail);
...
}
}
Then I have this RegisterRequest (mailable) class:
class RegisterRequest extends Mailable
{
use Queueable, SerializesModels;
protected $user;
public function __construct($user)
{
$this->user = $user;
}
public function build()
{
return $this->from('user#example.com')
->to($this->user->email)
->subject("Confirm your Email Address")
->view('emails.register.request')
->with("registration_token", $this->user->registration_token);
}
}
As you can see, I am using relational database to store jobs. And really, after calling LoginController's register method, a job is saved to database. But it can't be processed. I also start php artisan queue:work but nothing is done with jobs in database. Any help?
EDIT:
So I just found out that picking jobs from queue is done by SQL selecting the 'default' queue name. But I'm sending mails to queue 'emailsQueue'. So I'm now running Queue Worker like this: php artisan queue:work --queue=emailsQueue and everything's working fine for now. But how can I pick jobs from every queue in database? It's probably not the best attempt, right? It wouldn't make any sense to have named queues, right? But let's say I have one queue for processing register account requests, another queue for changing password requests and so on... So I think it does make sense to process every queue. So how can I do this? Can it be done just by listing the queues like this?
php artisan queue:work --queue=registerAccountEmailQueue,changePasswordEmailQueue...
What exactly does running php artisan queue:work? I thought it's the command to run all queues.
Use queue driver database.
In controller you should write
$this->dispatch(new SendNotifyMail($data));
This will pass your $data to queue. here SendNotifyMail is used as Job Class. So you should also use this in Controller like use App\Jobs\SendNotifyMail;.
Then create a file in Folder Jobs, named SendNotifyMail
<?php
namespace App\Jobs;
use App\Jobs\Job;
use DB;
use Mail;
use Artisan;
use Illuminate\Contracts\Mail\Mailer;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendNotifyMail extends Job implements ShouldQueue
{
use InteractsWithQueue, SerializesModels;
public $timeout = 300; // default is 60sec. You may overwrite like this
protected $data;
public function __construct($data)
{
$this->data = $data;
}
public function handle(Mailer $mailer)
{
$data = $this->data; // retrieve your passed data to variable
// your mail code here
}
}
In your command you need to write
php artisan queue:listen
or
php artisan queue:work
Then execute the code.

Laravel ShouldQueue How Does It Work

I know how to use ShouldQueue my question is about why does it work the way it does.
I need to edit how my new Job is stored in the database, and therefore am digging through Laravel's internals.
The job I want to edit is launched from the following event listener:
<?php
namespace App\Listeners;
use App\Events\NewMail;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Jobs\SendEmail;
use Carbon\Carbon;
class NewMailListener implements ShouldQueue
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param NewMail $event
* #return void
*/
public function handle(NewMail $event)
{
$addressee = $event->user->name;
$address = $event->user->email;
$type = "NewMail";
$job = (new SendEmail($type,$addressee,$address))->delay(Carbon::now()->addMinutes(10));
dispatch($job);
}
}
What I don't understand is how the ShouldQueue magic works, because in the source code it appears to do nothing.
<?php
namespace Illuminate\Contracts\Queue;
interface ShouldQueue
{
//
}
I understand it is a contract but it's not defining anything... so what it is doing exactly? Is there some auto-loading happening from the namespace?
I wasn't sure what an interface was exactly, so I looked at this: PHP Docs: Interfaces and came away with the impression that even if it is for decoupling, and interface should be defining something, which I don't see in ShouldQueue.
The top comment on that PHP docs page says this:
An INTERFACE is provided so you can describe a set of functions and
then hide the final implementation of those functions in an
implementing class. This allows you to change the IMPLEMENTATION of
those functions without changing how you use it.
But where is this description of functions here?
PS - I know this interface/contract is being used to queue the event listener itself, not the job that I want to edit. But I'm hoping understanding how the queue interacts with the event listener will better inform me as to how it works for the jobs.
Internally Laravel checks if Job or Mailable or Notification etc implements ShouldQueue interface. For example:
if ($job instanceof ShouldQueue) {
https://github.com/laravel/framework/blob/5.5/src/Illuminate/Console/Scheduling/Schedule.php#L86

Categories