DEV Community

Ayowande Oluwatosin
Ayowande Oluwatosin

Posted on

Job Batching in Laravel and Vue

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
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

Create a job called SendEmail using the artisan command:

php artisan make:job SendEmail
Enter fullscreen mode Exit fullscreen mode

Add batchable to jobs

use Illuminate\Bus\Batchable;

class SendEmail implements ShouldQueue
{
    use Batchable,  Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    ...
}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

In the routes/api.php create a new route

Route::get(batchupdate, 'MailController@checkBatchProgress');
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Top comments (0)