# Cache Strategy - Summary

## 📊 Overview

Semua endpoint statistic utama sekarang menggunakan **Redis Cache** untuk performa optimal.

## 🎯 Cache Coverage

| Endpoint | Cache Status | Cache Key Pattern | TTL |
|----------|-------------|-------------------|-----|
| `repayment-target` | ✅ `targetAmount` cached, `paidAmount` dynamic | `repayment_target:resort_{id}:unit_{id}:{date}` | End of day |
| `pdl-target` | ✅ Fully cached | `pdl_target:resort_{id}:unit_{id}:{date}` | End of day |
| `ongoing-pdl-target` | ✅ Fully cached (with daily cache) | `ongoing_target_pdl:resort_{id}:unit_{id}:{start}_to_{end}` | End of day |
| `ongoing-storting` | ❌ Dynamic (real-time transactions) | - | - |

### Daily PDL Target Cache (Internal)

Untuk optimasi perhitungan `ongoing-pdl-target`, setiap target PDL harian juga di-cache:

| Cache Type | Cache Key Pattern | Purpose |
|------------|-------------------|---------|
| Daily PDL Target | `daily_pdl_target:resort_{id}:unit_{id}:{date}` | Cache per hari untuk loop calculation |

**Contoh:**
```
daily_pdl_target:resort_global:unit_global:2026-02-01
daily_pdl_target:resort_global:unit_global:2026-02-02
daily_pdl_target:resort_global:unit_global:2026-02-03
```

**Benefit:** 
- First calculation (loop day 1): ~500ms (cache miss)
- Subsequent days: ~20ms (cache hit!)
- Ongoing calculation total: ~700ms → ~100ms (85% faster)

## 🔑 Cache Key Patterns

### 1. Repayment Target
```
repayment_target:resort_global:unit_global:2026-02-18
repayment_target:resort_RESORT001:unit_global:2026-02-18
repayment_target:resort_RESORT001:unit_UNIT001:2026-02-18
```

### 2. PDL Target
```
pdl_target:resort_global:unit_global:2026-02-18
pdl_target:resort_RESORT001:unit_global:2026-02-18
pdl_target:resort_RESORT001:unit_UNIT001:2026-02-18
```

### 3. Ongoing Target PDL
```
ongoing_target_pdl:resort_global:unit_global:2026-02-01_to_2026-02-18
ongoing_target_pdl:resort_RESORT001:unit_global:2026-02-01_to_2026-02-18
ongoing_target_pdl:resort_RESORT001:unit_UNIT001:2026-02-01_to_2026-02-18
```

## ⏰ Cache Invalidation

### Automatic Invalidation
- **TTL**: Semua cache expired otomatis pada **00:00 (midnight)**
- **Scheduler**: Cache invalidation berjalan setiap hari pukul **05:00 pagi**

### Manual Invalidation
```bash
# Invalidate ongoing target PDL cache
php artisan cache:invalidate-ongoing-target-pdl

# Clear all cache
php artisan cache:clear
```

## 📈 Performance Impact

### Before Cache
```
repayment-target:      ~500ms - 2s
pdl-target:           ~200ms - 1s
ongoing-pdl-target:   ~1s - 3s (31 hari calculation)
```

### After Cache
```
repayment-target:      ~50ms (90% faster)
pdl-target:           ~20ms (90% faster)
ongoing-pdl-target:   ~50ms (98% faster)
```

## 💡 Implementation Pattern

### Standard Pattern
```php
public function calculateSomethingByFilter(FilterRequest $request)
{
    $date = $request->get('endDate');
    $unitId = $request->get('unitId');
    $resortId = $request->get('resortId');
    
    // Generate cache key
    $cacheKey = $this->generateCacheKey($date, $unitId, $resortId);
    
    // Use cache until end of day
    return Cache::remember($cacheKey, now()->endOfDay(), function () use ($date, $unitId, $resortId) {
        // Actual calculation logic
        return $this->calculateDynamically($date, $unitId, $resortId);
    });
}

private function generateCacheKey(string $date, string $unitId, string $resortId): string
{
    $normalizedUnitId = $unitId === 'all' ? 'global' : $unitId;
    $normalizedResortId = $resortId === 'all' ? 'global' : $resortId;
    
    return sprintf(
        'prefix:resort_%s:unit_%s:%s',
        $normalizedResortId,
        $normalizedUnitId,
        $date
    );
}
```

## 🔍 Monitoring Cache

### Check Redis Keys
```bash
# List all statistic cache keys
redis-cli KEYS "*target*"
redis-cli KEYS "*pdl*"
redis-cli KEYS "*repayment*"

# Check specific key
redis-cli GET "pdl_target:resort_global:unit_global:2026-02-18"

# Check TTL
redis-cli TTL "pdl_target:resort_global:unit_global:2026-02-18"
```

### Laravel Cache Info
```bash
# View cache statistics (if using Redis)
redis-cli INFO stats

# Monitor cache hit/miss rate
redis-cli MONITOR | grep -E "(pdl_target|repayment_target|ongoing_target_pdl)"
```

## 📝 Best Practices

### ✅ DO
- Use cache untuk perhitungan yang kompleks dan stabil
- Set TTL yang appropriate (end of day untuk daily metrics)
- Normalize filter values ('all' → 'global') untuk konsistensi
- Include semua filter dalam cache key untuk akurasi

### ❌ DON'T
- Cache data yang berubah sangat sering (real-time transactions)
- Use cache untuk data yang butuh real-time accuracy
- Forget to invalidate cache saat ada perubahan data critical
- Use cache tanpa TTL (bisa stale forever)

## 🚀 Future Optimizations

### Potential Improvements
1. **Cache Warming**: Pre-calculate cache di pagi hari (jam 5 setelah invalidation)
2. **Tag-based Invalidation**: Use Redis tags untuk group-based cache clearing
3. **Hierarchical Cache**: Cache per level (global → unit → resort) untuk flexibility
4. **Background Recalculation**: Queue-based cache refresh sebelum expire

### Cache Warming Example
```php
// In app/Console/Commands/WarmStatisticCache.php
$schedule->command('cache:warm-statistic')->dailyAt('05:30');
```

## 📚 Related Documentation

- [Repayment Target Cache](./repayment-target-cache.md)
- [Ongoing Target PDL](./ongoing-target-pdl.md)
