问题
I have created an artisan command
that I want to run immediately after a method called. But the command contains a sleep();
command. I want to run that artisan command in background because the method need to return
immediately response to user. My sample code is a below:
In route file
Route::get('test', function(){
Artisan::queue('close:bidding', ['applicationId' => 1]);
return 'called close:bidding';
});
In close:bidding
command
public function handle()
{
$appId = $this->argument('applicationId');
//following code line is making the problem
sleep(1000 * 10);
//close bidding after certain close time
try{
Application::where('id', $appId)->update(['live_bidding_status' => 'closed']);
}catch (\PDOException $e){
$this->info($e->getMessage());//test purpose
}
$this->info($appId.": bid closed after 10 seconds of creation");
}
Problem
When I hit /test
url the return string called close:bidding
is being shown after 10 seconds browser loading, because there is a sleep(10 * 1000)
inside the command.
What I want
I want to run the command in background. I mean when I hit the /test
url it should immediately show up the called close:bidding
but close:bidding
command will be running in background. After 10 seconds it will update the application though the front-end user won't notice anything anything about it.
Partial Questions
Is it somehow related to
multi threading
?Is it something that cannot be solve using PHP, should I think differently?
Is there any way to solve this problem even using Laravel queue?
回答1:
Create a job
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class JobTest implements ShouldQueue
{
use InteractsWithQueue, Queueable, SerializesModels;
private $payload = [];
public function __construct($payload)
{
$this->payload = $payload;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$appId = $this->payload('applicationId');
//following code line is making the problem
sleep(1000 * 10);
}
}
To push job background queue
Route::get('test', function(){
dispatch((new JobTest)->onQueue('queue_name'));
return 'called close:bidding';
});
At this state we have job and you dispath the job to the queue. But it not processed yet. We need queue listener or worker to process those job in background
php artisan queue:listen --queue=queue_name --timeout=0
OR
php artisan queue:work --queue=queue_name --timeout=0 //this will run forever
Note: May be you can try supervisord,beanstakd for manage queue
For more info refer this
回答2:
If you don't need all advantages of proper queue, which come at a price, it may be sufficient to use terminate middleware. It will do the job after response was sent to the browser.
来源:https://stackoverflow.com/questions/41205924/how-to-sleep-phplaravel-5-2-in-background