I need a way to run some tasks asynchronously as the execution time varies between each task and I want to run the in an asynchronous way using Laravel Jobs and database as the driver.
I created to test jobs using the command line: php artisan make:job TestOne php artisan make:job TestTwo
TestOne.php
<?php
namespace App\Jobs;
use App\Jobs\Job;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class TestOne extends Job implements ShouldQueue
{
use InteractsWithQueue, SerializesModels;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
sleep(5);
foreach (range(1, 10) as $item)
\Log::info("TestOne: item #" . $item);
}
}
TestTwo.php
<?php
namespace App\Jobs;
use App\Jobs\Job;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class TestTwo extends Job implements ShouldQueue
{
use InteractsWithQueue, SerializesModels;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
foreach (range(1, 10) as $item)
\Log::info("TestTwo: item #" . $item);
}
}
I simply log some messages in laravel's log file, and since TestOne is sleeping for 5 seconds, TestTwo should log the messages first
HomeController.php
<?php
namespace App\Http\Controllers;
use Queue;
use App\Jobs\TestOne;
use App\Jobs\TestTwo;
class HomeController extends Controller
{
public function index()
{
$this->dispatch(new TestOne());
$this->dispatch(new TestTwo());
die("stop");
}
}
However TestTwo job still waits until TestOne job is done:
[2017-03-04 17:00:30] local.INFO: TestOne: item #1
[2017-03-04 17:00:30] local.INFO: TestOne: item #2
[2017-03-04 17:00:30] local.INFO: TestOne: item #3
[2017-03-04 17:00:30] local.INFO: TestOne: item #4
[2017-03-04 17:00:30] local.INFO: TestOne: item #5
[2017-03-04 17:00:30] local.INFO: TestOne: item #6
[2017-03-04 17:00:30] local.INFO: TestOne: item #7
[2017-03-04 17:00:30] local.INFO: TestOne: item #8
[2017-03-04 17:00:30] local.INFO: TestOne: item #9
[2017-03-04 17:00:30] local.INFO: TestOne: item #10
[2017-03-04 17:00:30] local.INFO: TestTwo: item #1
[2017-03-04 17:00:30] local.INFO: TestTwo: item #2
[2017-03-04 17:00:30] local.INFO: TestTwo: item #3
[2017-03-04 17:00:30] local.INFO: TestTwo: item #4
[2017-03-04 17:00:30] local.INFO: TestTwo: item #5
[2017-03-04 17:00:30] local.INFO: TestTwo: item #6
[2017-03-04 17:00:30] local.INFO: TestTwo: item #7
[2017-03-04 17:00:30] local.INFO: TestTwo: item #8
[2017-03-04 17:00:30] local.INFO: TestTwo: item #9
[2017-03-04 17:00:30] local.INFO: TestTwo: item #10
I am running the jobs with php artisan queue:listen
What am I doing wrong here? I really need these tasks to run asynchronously, just like, say, a JS AJAX request would work like.
I am using Laravel 5.2. Again, I am using "database" as the queue driver and yes I have migrated the jobs table. Is it not possible using the database as the driver?
To process jobs in parallel you'd have to split them across different queues as @dparoli pointed out.
This way you can not only categorize them but also priorize how they'll be processed by your queue workers.
When dispatching a job, you'll specify which queue it belongs:
$this->dispatch((new TestOne())->onQueue('queue1'));
$this->dispatch((new TestTwo())->onQueue('queue2'));
That way you can spawn multiple queue workers to process jobs separately:
php artisan queue:work --queue=queue1
php artisan queue:work --queue=queue2
You can also use a single queue worker which priorize how queues are processed, so you can give a higher or lower precedence for some jobs over others:
php artisan queue:work --queue=queue2,queue1
By using a process monitor like Supervisor you can even spawn a single worker in multiple processes as detailed in the documentation.
It's worth noting that a single queue worker which prioritizes its queues will still process their jobs by taking the FIFO precedence in addition to the given queue priority. To achieve a better parallelism you'll want to spawn multiple queue workers.
This holds true for all queue drivers.