Laravel queue enables us to run processes in the background and avoid us having to wait for a response. This functionality enables us to be able to run heavy processes with slowing down browser/ user experience. However, what if the user would like to get real-time update on the processes going on in the background? The best way is to present live information or a progress bar. From Laravel 8, we have Job Batching.
According to Laravel doc, Laravel's job batching feature allows you to easily execute a batch of jobs and then perform some action when the batch of jobs has completed executing.
To get started, we would need a database migration to create our table to contain information about job batching:
php artisan queue:batches-table
php artisan migrate
In the MailController,
use Illuminate\Bus\Batch;
use Illuminate\Support\Facades\Bus;
use App\Models\User;
public function runJob(Request $request)
{
$users= User::get();
//create a batch queue
$batch = Bus::batch([
//All jobs here
new SendEmail($users),
])->then(function (Batch $batch) {
// All jobs completed successfully...
logger('Batch ' . $batch->id . ' finished successfully!');
})->catch(function (Batch $batch, Throwable $e) {
// First batch job failure detected...
logger('Batch ' . $batch->id . ' did not finish successfully!');
})->finally(function (Batch $batch) {
// The batch has finished executing...
logger('Cleaning leftovers from batch ' . $batch->id);
}) ->name('send_email)->dispatch();
return $batch->id;
}
public function checkBatchProgress()
{
$batches = DB::table('job_batches')->where([['pending_jobs','>',0],['name','=','send_email’]])->orderBy('created_at', 'desc')->limit(10)->get();
if(count($batches) > 0){
$job_status = Bus::findBatch($batches[0]->id)->toArray();
$response = round($job_status['progress'],0);
return $response;
}else{
$response = 0;
return $response;
}
}
Create a job called SendEmail using the artisan command:
php artisan make:job SendEmail
Add batchable to jobs
use Illuminate\Bus\Batchable;
class SendEmail implements ShouldQueue
{
use Batchable, Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
...
}
To create a progress bar, we need to add code to SendEmail.vue:
<template>
<div>
<div class="progress">
<div class="progress-bar" role="progressbar" :aria-valuenow="timer"
aria-valuemin="0" aria-valuemax="100" :style={width:timer +’%’}">{{
<span class="sr-only">{{timer}}% Complete</span>
</div>
</div>
</div>
</template>
<script>
data() {
return {
timer: 0
}
},
mounted: function () {
//run the function every 1 second
this.timer = setInterval(() => {
this.batchProgress()
}, 1000)
},
beforeDestroy() {
clearInterval(this.timer)
},
methods: {
batchProgress(){
//make a fetch or axios request to the endpoint
axios.get('/api/batchupdate').then(response=>{
this.timer = response.data;
})
},
</script>
In the routes/api.php create a new route
Route::get(batchupdate, 'MailController@checkBatchProgress');
Finally, don't forget to instruct your application to use the database driver by updating the QUEUE_CONNECTION variable in your application's .env file:
QUEUE_CONNECTION=database
Top comments (0)