Membuat Job Queue Batching pada Laravel dengan Indikator Proses Secara Realtime Menggunakan Pusher
Tags: laravel, programming
Published: 2024-06-02 12:02:31

![Konsep FIFO (First in First out) pada Queue](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4gi3m0th0h2h5v0tdb0g.png)

Queue adalah salah satu bentuk struktur data dasar dari sebuah proses program atau kita bisa menyebutnya dengan istilah antrian. Konsep yang paling sering didengar dari Queue ini adalah FIFO (First in First out). Konsep FIFO ini dapat kita lihat dalam kehidupan sehari-hari contohnya, ketika kita membeli makanan dengan sistem layanan drive thru maka kendaraan yang pertama datang akan dilayani terlebih dahulu kemudian akan keluar terlebih dahulu juga setelah selesai membeli makanan.

Seberapa penting penerapan queue pada program aplikasi yang kita buat? Tentu jawabannya adalah sangat penting. Contoh kasus sederhananya ketika kita mengeksekusi proses update data ke dalam database dengan jumlah data yang banyak tentunya browser tidak akan mungkin menunggu proses update itu hingga selesai. Biasanya akan terjadi timeout dikarenakan browser tidak mendapatkan respon apapun dari server, sedangkan disisi lain sebenarnya server sedang menjalankan proses itu namun dikarenakan prosesnya lama maka browser akan menganggap waktu tunggunya sudah selesai. Kurang lebih contoh sederhananya seperti itu.

Lalu bagaimana cara menerapkan konsep Queue menggunakan Laravel? disini ada beberapa langkah yang perlu disiapkan supaya kita bisa menerapkan konsep queue pada projek Laravel kita.

### Persyaratan

- [PHP 7.4 atau lebih](https://www.php.net/)
- [Laravel 8 atau lebih](https://laravel.com/)
- [Laravel Queue](https://laravel.com/docs/11.x/queues)
- [Pusher](https://pusher.com/)

### Migration Table Job & Job Batches

Berikut adalah langkah-langkah untuk menyiapkan tabel jobs dan job_batches

Jalankan perintah dibawah ini untuk membuat tabel jobs :

```bash
php artisan queue:table
```

Jalankan perintah dibawah ini untuk membuat tabel job_batches :

```bash
php artisan queue:batches-table
```

Lakukan migrasi tabel menggunakan perintah dibawah ini :

```bash
php artisan migrate
```


### Install Package Realtime Job Batching
Jalankan perintah dibawah ini untuk melakukan instalasi package :

```bash
composer require yogameleniawan/realtime-job-batching
```


### Konfigurasi Pusher
Berikut adalah langkah-langkah untuk konfigurasi Pusher :

Install Pusher PHP SDK
```bash
composer require pusher/pusher-php-server
```
Buat Channels App Pusher [klik disini](https://dashboard.pusher.com/)

Setting file .env untuk Pusher Variable
```bash
PUSHER_APP_ID=your_pusher_app_id
PUSHER_APP_KEY=your_pusher_app_key
PUSHER_APP_SECRET=your_pusher_app_secret
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME=https
PUSHER_APP_CLUSTER=mt1
```

### Membuat Repository Class
Berikut langkah-langkah yang dilakukan untuk membuat Repository Class :

Buat file contoh: **VerificationRepository.php** pada folder **root_project/app/Repositories**

> Untuk lokasi folder bisa dibuat secara bebas. Apabila menggunakan arsitektur lain seperti Modular, DDD, dan lain-lain bisa disesuaikan dengan struktur projeknya.


Repository Class yang sudah dibuat mengimplementasikan interface RealtimeJobBatchInterface yang sudah dibuat pada package ini. Kemudian silahkan tambahkan function get_all(): Collection dan save($data): void.


**Penjelasan**


> _public function get_all(): Collection_
> function ini digunakan untuk mengambil semua data pada database kemudian dikembalikan dalam bentuk Collection. Tujuan dikembalikan dalam bentuk collection ini karena kita perlu melakukan looping lalu setiap looping, prosesnya akan kita masukkan ke dalam queue.

**Penjelasan**

> _public function save($data): void_
> function ini digunakan untuk melakukan proses penyimpanan ataupun perubahan yang akan terjadi dalam 1 proses queue. Kita bisa membuat bisnis proses sendiri sesuai dengan kebutuhan di dalam function ini.

```php
<?php
namespace App\Repositories;

use App\Models\User;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use YogaMeleniawan\JobBatchingWithRealtimeProgress\Interfaces\RealtimeJobBatchInterface;
class VerificationRepository implements RealtimeJobBatchInterface {
    public function get_all(): Collection {
        $sql = "SELECT * FROM users";
        return collect(DB::select($sql));
    }
    public function save($data): void {
        DB::table('users')
        ->where('id', $data->id)
        ->update([
            'is_verification' => true,
        ]);
    }
}
```

Buat Function Controller untuk menjalankan proses yang ada di dalam repository yang sudah dibuat sebelumnya.
Contoh :

Tambahkan 2 baris ini untuk melakukan import class yang kita gunakan.

```php
use App\Repositories\VerificationRepository;
use YogaMeleniawan\JobBatchingWithRealtimeProgress\RealtimeJobBatch;
```

Kemudian buat function untuk menjalankan proses queue.

```php
public function verification() {
    $batch = RealtimeJobBatch::setRepository(new VerificationRepository())
              ->execute(name: 'User Verification');

    return response()
        ->json([
            'message' => 'User verification is running in background',
            'batch' => $batch
      ], 200);
}
```

**Penjelasan**

> _setRepository(new VerificationRepository())_
> Pada parameter function setRepository kita bisa mengirim berdasarkan repository class yang kita gunakan. Tujuannya supaya class RealtimeJobBatch dapat digunakan di berbagai jenis service dengan implementasi proses yang berbeda-beda.
> _->execute(name: 'User Verification')_
> Di dalam parameter function execute kita bisa menuliskan nama dari job_batches yang digunakan untuk menyimpan informasi proses job queue yang sedang berjalan.

### Setup Javascript
Berikut langkah-langkah yang dilakukan untuk melakukan setup javascript :

Pada konfigurasi javascript ini menggunakan blade. Apabila ingin menggunakan selain blade dapat dilihat pada dokumentasi berikut ini.

Tambahkan `<script>` ini ke dalam file blade :

```javascript
<script src="https://js.pusher.com/7.2/pusher.min.js"></script>
<script>
    var pusher = new Pusher('YOUR_PUSHER_APP_KEY', {
        cluster: 'mt1'
    });
    var channel = pusher.subscribe('channel-job-batching');
    channel.bind('broadcast-job-batching', function(data) {
        console.log(data)
    });
</script>
```

`YOUR_PUSHER_APP_KEY ` bisa diisikan value sesuai dengan `PUSHER_APP_KEY ` pada file `.env`

Untuk sementara waktu "channel-job-batching" dan "broadcast-job-batching" adalah nama default yang harus ditulis. Apabila menggunakan selain nama itu maka tidak akan mendapatkan response dari Pusher. Untuk update package berikutnya akan dikembangkan fitur pemberian nama channel secara bebas.

Hasil response dari Pusher :

```json
{
  "finished": false,
  "progress": 10,
  "pending": 90,
  "total": 100,
  "data": {}
},
```

Isi dari key "data" akan berupa object sesuai dengan data yang sedang diproses.

Contoh :

Update user dengan id 10 sedang dijalankan. Maka nilai object dari key "data" yaitu sesuai dengan atribut yang dimiliki oleh tabel, contoh :
Atribut Tabel User :

- id
- name
- email
- is_verified

Maka hasil response dari pusher seperti ini :

```json
{
  "finished": false,
  "progress": 10,
  "pending": 90,
  "total": 100,
  "data": {
      "id": 10,
      "name": "Yoga Meleniawan Pamungkas",
      "email": "yogameleniawan@gmail.com",
      "is_verified": true,
  }
},
```

### Notes
Package realtime-job-batching masih perlu banyak pengembangan. Seiring berjalannya waktu proses pengembangan package akan dilakukan berdasarkan bug ataupun keperluan penambahan fitur.