# Setup Guide: Queue System untuk SAP Sync

## Overview
Sistem ini menggunakan **Laravel Queue dengan Database Driver** untuk memproses sync data SAP di background. Ini memungkinkan:
- Sync data besar tanpa timeout
- Progress tracking real-time
- Retry mechanism jika gagal
- User tetap bisa menggunakan aplikasi saat sync berjalan

---

## Step-by-Step Setup

### 1. **Jalankan Migration** (Lakukan sekali)
```bash
php artisan migrate
```
Migration yang akan dijalankan:
- `jobs` table - Menyimpan queue jobs
- `failed_jobs` table - Menyimpan failed jobs untuk retry
- `rpt_sync_status` table - Tracking status sync

### 2. **Konfigurasi Queue Driver** (.env)
Pastikan `.env` Anda menggunakan database driver:
```env
QUEUE_CONNECTION=database
```

Jika masih `sync`, ubah ke `database`:
```env
# Ubah dari
QUEUE_CONNECTION=sync

# Menjadi
QUEUE_CONNECTION=database
```

### 3. **Jalankan Queue Worker** (WAJIB - Ini yang memproses job)
Queue worker adalah proses yang berjalan di background untuk mengeksekusi job.

**Cara 1: Run Sekali (Testing)**
```bash
php artisan queue:work --stop-when-empty
```
- Proses semua job yang pending
- Berhenti setelah selesai
- Cocok untuk testing

**Cara 2: Run Continuously (Production)**
```bash
php artisan queue:work --tries=3 --timeout=3600
```
- Terus berjalan dan memproses job baru
- Restart otomatis setelah 3600 detik (1 jam)
- Mencoba ulang failed job 3x

**Cara 3: Daemon dengan Auto-Restart (Recommended untuk Server)**
Gunakan **Supervisor** (Linux) atau **nssm** (Windows) untuk keep worker running.

Untuk Windows (menggunakan PowerShell):
```powershell
# Buka window baru dan jalankan:
php artisan queue:work --tries=3 --timeout=3600 --sleep=3
```

### 4. **Cek Status Queue**
```bash
# Lihat job yang pending
php artisan queue:monitor database

# Lihat failed jobs
php artisan queue:failed

# Retry failed job
php artisan queue:retry [job-id]

# Retry semua failed jobs
php artisan queue:retry all

# Hapus failed job
php artisan queue:forget [job-id]

# Flush semua failed jobs
php artisan queue:flush
```

---

## Workflow Penggunaan

### Flow 1: Sync Baru
1. User klik **"Sync & View"**
2. System membuat record di `rpt_sync_status` (status: **pending**)
3. System dispatch **SapBillingSyncJob** (untuk ZVBILLING) dan **SapFinanceYieldSyncJob** (untuk ZFFINANCE_YIELD) ke queue
4. User di-redirect ke **Status Page**
5. Queue Worker pick up job dan mulai proses (status: **processing**)
6. Progress diupdate real-time (tiap 3 detik via AJAX)
7. Setelah selesai, status menjadi **completed**
8. User bisa klik **"View Data"** untuk lihat hasil

### Flow 2: View Data (Tanpa Sync)
1. User klik **"View"**
2. System langsung tampilkan data dari database
3. Tidak ada queue job yang dibuat

### Flow 3: Cek Status
1. User klik **"History"** atau menu Status
2. System tampilkan list semua sync
3. User bisa kli **Detail** untuk melihat progress

---

## Troubleshooting

### Issue 1: Sync Status Stuck di "Pending"
**Penyebab:** Queue worker tidak berjalan
**Solusi:**
```bash
php artisan queue:work
```

### Issue 2: Sync Failed
**Cek Log:**
```bash
tail -f storage/logs/laravel.log
```

**Retry Failed Job:**
```bash
php artisan queue:retry all
```

### Issue 3: "Driver [database] not supported"
**Penyebab:** Belum jalankan migration jobs table
**Solusi:**
```bash
php artisan migrate
```

### Issue 4: Timeout saat Fetch SAP
Job sudah di-set timeout 1 jam (3600 detik). Jika masih timeout:
- Cek koneksi SAP
- Cek apakah data SAP terlalu besar
- Pertimbangkan fetch per bulan (bukan per tahun)

---

## Performance Tuning

### Chunk Size
Di `SapBillingSyncJob.php` dan `SapFinanceYieldSyncJob.php`, chunk size default 500 records:
```php
$chunkSize = 500;
```

**Jika server kuat:** Naikkan ke 1000-2000
**Jika server lemah:** Turunkan ke 200-300

### Queue Worker Optimization
```bash
# Memory-efficient mode
php artisan queue:work --memory=512 --tries=3 --timeout=3600

# Sleep when no jobs (hemat CPU)
php artisan queue:work --sleep=3 --tries=3 --timeout=3600
```

---

## Monitoring

### Log File
Semua aktivitas queue tercatat di:
```
storage/logs/laravel.log
```

Cek dengan:
```bash
tail -f storage/logs/laravel.log | grep -i "SapBillingSyncJob\|SapFinanceYieldSyncJob"
```

### Database Query
```sql
-- Cek job yang sedang berjalan
SELECT * FROM rpt_sync_status WHERE status = 'processing';

-- Cek history sync
SELECT * FROM rpt_sync_status ORDER BY created_at DESC LIMIT 10;

-- Cek queue
SELECT * FROM jobs;

-- Cek failed jobs
SELECT * FROM failed_jobs;
```

---

## Commands Ringkasan

```bash
# Setup (sekali saja)
php artisan migrate

# Development (testing)
php artisan queue:work --stop-when-empty

# Production (continuous)
php artisan queue:work --tries=3 --timeout=3600

# Monitoring
php artisan queue:monitor database
php artisan queue:failed

# Maintenance
php artisan queue:retry all      # Retry all failed
php artisan queue:flush          # Hapus semua failed

# AUTO-SYNC COMMANDS (Baru - ensures no stuck pending syncs)
php artisan sap:auto-sync              # Run cleanup + dispatch (recommended)
php artisan sap:cleanup-stuck          # Mark stuck syncs as failed
php artisan sap:dispatch-pending       # Dispatch pending syncs to queue
php artisan sap:dispatch-pending --dry-run  # Preview what would be dispatched
```

---

## Auto-Sync System (Anti-Stuck)

Sistem ini memastikan tidak ada sync yang stuck di status `pending` atau `processing` selamanya.

### Cara Kerja:
1. **Auto-Cleanup** (setiap 10 menit):
   - Sync `processing` > 60 menit → Mark as failed
   - Sync `pending` > 30 menit tanpa job di queue → Mark as failed
   - Sync dengan job_id tapi job tidak ada di queue → Mark as failed

2. **Auto-Dispatch** (setiap 5 menit):
   - Cari sync dengan status `pending`
   - Cek apakah job sudah ada di queue
   - Kalau belum, dispatch job ke queue
   - Maksimal 5 sync per run

### Scheduled Tasks (Auto-Run):
Task scheduler sudah dikonfigurasi di `app/Console/Kernel.php`:
- Cleanup: Setiap 10 menit
- Dispatch: Setiap 5 menit

**Pastikan scheduler berjalan:**
```bash
# Linux (cron)
* * * * * cd /path/to/project && php artisan schedule:run >> /dev/null 2>&1

# Windows (Task Scheduler)
# Buat task yang run every minute: php artisan schedule:run
```

### Commands Manual:
```bash
# Auto-run lengkap (cleanup + dispatch)
php artisan sap:auto-sync

# Cek dan bersihkan stuck syncs saja
php artisan sap:cleanup-stuck
php artisan sap:cleanup-stuck --dry-run  # Preview only

# Dispatch pending syncs saja
php artisan sap:dispatch-pending
php artisan sap:dispatch-pending --max=20  # Dispatch up to 20
```

### Monitoring:
```sql
-- Cek sync yang stuck
SELECT * FROM rpt_sync_status 
WHERE status IN ('pending', 'processing') 
AND created_at < DATE_SUB(NOW(), INTERVAL 30 MINUTE);

-- Cek statistik
SELECT 
    status, 
    COUNT(*) as count,
    MAX(updated_at) as last_update
FROM rpt_sync_status 
GROUP BY status;
```

---

## Tips Produksi

1. **Selalu jalankan queue worker** di server (gunakan Supervisor/nssm)
2. **Monitor log** secara berkala untuk error
3. **Set retry** job untuk handle temporary failures
4. **Jalankan migrate** sebelum deploy
5. **Backup database** sebelum sync besar
6. **Enable scheduler** untuk auto-cleanup (penting!)

## Struktur File yang Dibuat/Dimodifikasi

### Files Baru:
- `app/Jobs/SapBillingSyncJob.php` - Job class untuk sync ZVBILLING
- `app/Jobs/SapFinanceYieldSyncJob.php` - Job class untuk sync ZFFINANCE_YIELD_ACCOUNTING
- `app/Console/Commands/SapSyncAutoRun.php` - Auto-run cleanup + dispatch
- `app/Console/Commands/DispatchPendingSync.php` - Dispatch pending syncs command
- `app/Console/Commands/CleanupStuckSyncs.php` - Cleanup stuck syncs command
- `database/migrations/2026_05_11_111021_create_rpt_sync_status_table.php` - Tracking table
- `resources/views/report/rptptr/status.blade.php` - Status monitoring page
- `resources/views/report/rptptr/status_list.blade.php` - History list page

### Files Dimodifikasi:
- `app/Http/Controllers/RptptrController.php` - Dispatch job & status tracking
- `resources/views/report/rptptr/filter.blade.php` - Tambah history panel
- `routes/web.php` - Tambah route status
- `app/Http/Controllers/PageController.php` - Handle status action
