I would like to push another job onto the queue after my first one has successfully executed. From my ShopController.php I fire:
$this->dispatch(new ItemPurchased($myVariables));
In ItemPurchased.php:
public function handle()
{
// some code that charges a user's credit card
}
How do i fire a subsequent job upon success of ItemPurchased.php?
From the Laravel Documentation, you would do something like this in a ServiceProvider:
{
Queue::after(function (JobProcessed $event) {
// $event->connectionName
// $event->job
// $event->data
});
}
But how do i specify, after ItemPurchase.php was successfuly, then dispatch another job? There is a failed() method for code to run when jobs fail. Is there a success() method that hasn't been mentioned before?
Jobs run offline through the Queue driver. However, once the handle method is called it follows the normal sync code execution.
So simply at the end of handle method just fire the new job:
public function handle()
{
//Some code here
dispatch(new JobClass());
}
Related
when I create a job and before start it , I need run a function ,
i update the class DatabaseJob
<?php
namespace App\Queue\Jobs;
use App\Models\Tenancy;
use App\Http\DatabaseHelper;
use App\Http\Helper;
class DatabaseJob extends \Illuminate\Queue\Jobs\DatabaseJob
{
public function fire()
{
Helper::createJobLog($this->job->id);
parent::fire();
}
}
but it seems the function createJobLog is fired only when the Job start ,I need it when the job created not started .
In a service provider you can listen for the Illuminate\Queue\Events\JobQueued event. Something similar to:
Event::listen(JobQueued::class, function ($event) {
// Of course, if you need to log only the database jobs then you can check the job type
if (!$event->job instanceOf DatabaseJob) {
return;
}
Helper::createJobLog($event->job->getJobId());
});
You may call the function createJobLog() when the job is dispatched. Jobs can be set with a timestamp to delay its start time, if you don’t want the job started immediately after it is being dispatched.
I need to save the request into the database after that i have to call an API to sync the data to the other server.
i do the API call using the finally but it seems PHP still processing it, even when i am sending the response in the try clause.
how do i make this asynchronous ? i want to send the response as fast as possible but still processing the API call after the response.
so this what the simple code look like, describing what i am currently doing.
Code with finally =>
public function store(Request $request)
{
try {
//returning the code early
return response("i am speed", 202);
} catch (\Throwable $th) {
return response($th->getMessage(), 500);
} finally {
//lets says this is the super long too run
$i = 0;
$last = 11111111;
while ($i <= $last) {
$i++;
}
}
}
//this code finish in 1000ms
code without finally =>
public function store(Request $request)
{
try {
return response("i am speed", 202);
} catch (\Throwable $th) {
return response($th->getMessage(), 500);
}
} //this code finish in 90ms;
why this is happen ?
i already sending the response but why it not returning early ?
what can i do to send the response first then continue the execution ?
I already finish this problem.
As the comment suggest Laravel have a feature called a queue that will dispatch the job the database, this process won't running until you run the queue worker.
To make queue what i do is :
First change the .env QUEUE_CONNECTION to database.
QUEUE_CONNECTION=database
Then run this artisan command to setup the queue worker.
php artisan queue:table
php artisan migrate
After that make a job for the function that want to run in the queue.
For example i am gonna put the finally code (the one in the question) in the new job.
php artisan make:job exampleJobName
Then go to exampleJobName.php, write the code that will be running in the queue in the handle function.
public function handle()
{
//lets says this is the super long too run code
$i = 0;
$last = $this->data; //variable from constructor
while ($i <= $last) {
$i++;
}
}
//exampleJobName.php
If a variable need to be pass to the handle, then add a contructor in the __construct function.
public function __construct($data)
{
$this->data = $data;
}
//still inside the exampleJobName.php
Then everything is setup go to the controller that want to run this job (i am gonna take example from question) and change the code to this.
public function store(Request $request)
{
try {
$data = 111111111;
exampleJobName::dispatch($data);
//this will insert the job on the jobs table in the database
//therefore the job won't run until the queue worker is running
return response("i am speed", 202);
} catch (\Throwable $th) {
return response($th->getMessage(), 500);
}
}
//this code finish fast
Everything is ready then just run the queue worker in the terminal side by side with artisan serve.
php artisan queue:work
The queue worker will check to the jobs table if there are any job that hasn't run yet. then will run it one by one.
That's what i do, hope this can help someone.
credit to Tim Lewis in the comment for show me this this link.
Call an API to sync the data to the other server potentially can take a long time so I suggest that you create and dispatch a job for that.
If you still want to do so right after the response is sent, you might want to use dispatchAfterResponse.
I would like to modify a session variable when my queue job has finished. I found in laravel documentation, that Queue::after is created for my issue, but I can not find out how to use it.
I start the job from a controller: VideoController.php
$job = (new VideoConvertJob($newFileName))->delay(Carbon::now()->addSeconds(5)); dispatch($job);
There are some code in the job (VideoConvertJob.php) handle method:
public function handle() { ... }
But I do not know, where and how should I imlement the Queue::after method, to know that job has finished succesfully and update my session.
I want to create new job which will be called by Amazon SQS and using Laravel Queue to push queues.
Currently, I have one job that works perfectly, but when I create another job as below, it has not been called.
class SimpleJob
{
public function fire($job, $data)
{
DB::table('product_prices')
->insert(array('product_id' => 1557,'price' => 100));
$this->success();
}
private function success()
{
$this->job->delete();
}
private function fail($messages = array())
{
Log::error('Job processing fail', $messages);
$this->job->delete();
}
}
I did read this doc but still cannot figure it out.
I am sure that SQS really sent a message since the old job can still be called.
Apart from creating job class and put everything in fire(), what else I need to do when creating new jobs?
This is Laravel 4.2.
I want to do something like this in my fire method:
class MyClass{
public function fire($job) {
if(something) {
$job->fail();
}else {
//processing
}
$job->delete();
}
There is no such method as fail(), is it possible to do something like this?
There is no such thing as fail a job but what you can do:
release it back to the queue with
$job->release();
After defined number of attempts it will end up in failed jobs table.
throw an exception. The job will be released back to the queue on it's own.
if you're using beanstalkd as a queue driver you can bury a job
$job->bury();
If your condition is unrecoverable you can log this fact and simply delete the job.