do i able to run exec() on queue jobs for laravel - php

now im doing laravel project and i want to run a command exec() on queue jobs. the Question is, do i really can run the command exec() on queue jobs?
this what i've done, i create a jobs file call app/Jobs/GetData.php and create a simple code.
<?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;
class GetData implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct()
{
//
}
public function handle()
{
$csvFileName = public_path("csv/nintendo.csv");
$process = exec('facebook-scraper --filename '.$csvFileName.' --pages 1 '.$this->record->facebook_id);
}
}
but not success to run the exec().. if i implement this code on controller file. i can success to run the command and download the .CSV file.
before i tried to use this
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
-----
$csvFileName = public_path("csv/nintendo.csv");
$process = new Process("facebook-scraper --filename ".$csvFileName." --pages 5 nintendo");
$process->run();
// executes after the command finishes
if (!$process->isSuccessful()) {
//execute failed code
}else{
//execute success code
}
$process->getOutput();
but this also not working.. please help how to execute the command inside the queue jobs on laravel.

To solve the issue of non working command you have to either create env variables which points to Facebook-scraper or use the full path(absolute not relative) of facebook scraper package.
So the process construction should be something like
$process = new Process("/full-path/of/facebook-scraper --filename ".$csvFileName." --pages 5 nintendo");
$process->run();

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

add job to queue Laravel

i got a problem when execute my queue. Job doesnt work.
.env:
QUEUE_CONNECTION=database_name
Job:
use App\Models\ProfessorSuscriptionHistory;
class CheckSuscription implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct()
{
}
public function handle()
{
$suscription_history = new ProfessorSuscriptionHistory();
$suscription_history->user_id = 13;
$suscription_history->type = 'trimestral';
$suscription_history->pdf = 'test.pdf';
$suscription_history->ended_at = Carbon::now()->addMonth(3);
$suscription_history->save();
}
}
My controller what dispatch a Job
use App\Jobs\CheckSuscription;
class TestController extends Controller
{
public function index()
{
CheckSuscription::dispatch()->onQueue('processing');
}
}
i used command php artisan queue:work and php artisan queue:listen but nothing appear in cmd. i migrated jobs to my db using php artisan queue:table and nothing appear in jobs table or failed_jobs table too. How can i fix that? thx!!
Put your QUEUE_CONNECTION=database_name to just QUEUE_CONNECTION=database you dont put the database name you just tell Laravel to use a certain queue. database, redis ...
Queue Connection

Lumen prevent duplicate job in a queue

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

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.

Categories