Cache
Layer caching berbasis Redis dengan TTL, invalidasi otomatis, dan graceful degradation
RESTForge menyediakan Redis-based caching layer yang bekerja otomatis pada operasi READ dan melakukan invalidasi otomatis pada operasi WRITE. Cache meningkatkan performa API dengan menyimpan hasil query di Redis sehingga request berikutnya dengan parameter yang sama tidak perlu mengakses database.
Referensi Cepat (Quick Reference)
| Properti | Nilai |
|---|---|
| Dependency | Redis Server 6.0+ |
| Aktivasi | CACHE_ENABLED=true di file .env |
| Default TTL | 300 detik (5 menit) |
| Invalidasi | Otomatis saat operasi WRITE (INSERT/UPDATE/DELETE) |
| Graceful degradation | Jika Redis down saat runtime, request langsung ke database |
| Endpoint di-cache | /datatables, /read, /lookup (static dan filter), processor |
| Endpoint tidak di-cache | /first, /lookup (dynamic keystroke), /read-composite, operasi WRITE |
Konfigurasi (Configuration)
Koneksi Redis (Redis Connection)
REDIS_HOST=localhost
REDIS_PORT=6380
REDIS_PASSWORD=
REDIS_DB=0Pengaturan Cache (Cache Settings)
CACHE_ENABLED=true
CACHE_TTL=300| Variable | Tipe | Default | Keterangan |
|---|---|---|---|
CACHE_ENABLED | boolean | false | Aktifkan/nonaktifkan cache secara global |
CACHE_TTL | number | 300 | TTL (Time-To-Live) dalam detik, berlaku untuk semua operasi |
RESTForge menggunakan satu nilai TTL untuk semua operasi karena semua endpoint yang di-cache query ke tabel yang sama, dan saat operasi WRITE terjadi, semua cache endpoint tersebut di-invalidasi sekaligus.
Endpoint yang Di-cache (Cached Endpoints)
| Endpoint | Cache Type | Identifier |
|---|---|---|
POST /datatables | datatables | MD5 hash dari parameter (search, filter, pagination, sort) |
POST /read | list | MD5 hash dari parameter (filter, pagination) |
POST /lookup (static) | lookup_static | all (seluruh data) |
POST /lookup (filter) | lookup_filter | MD5 hash dari where clause |
Endpoint yang Tidak Di-cache
| Endpoint | Alasan |
|---|---|
POST /first | Single record, selalu butuh data terbaru |
GET /lookup (keystroke) | Variasi input terlalu tinggi, hit rate rendah |
POST /read-composite | Data composite (header + detail), kompleksitas tinggi |
| Operasi WRITE | /create, /update, /delete tidak di-cache |
Cara Kerja (How It Works)
Alur Operasi READ
POST /api/{project}/{endpoint}/datatables
│
├── Cache ENABLED?
│ ├── Ya → Build cache key → Cek Redis
│ │ ├── HIT → Return cached result (~1-3ms)
│ │ └── MISS → Query database (~50-200ms) → Simpan ke Redis → Return
│ └── Tidak → Query database langsung
│
└── HTTP ResponseAlur Invalidasi saat WRITE
POST /api/{project}/{endpoint}/create (atau /update, /delete)
│
├── Execute SQL (INSERT/UPDATE/DELETE)
│ ├── COMMIT berhasil
│ │ ├── Self invalidation: hapus rf:{project}:{endpoint}:*
│ │ └── Cascade invalidation: hapus cache processor yang bergantung pada tabel ini
│ └── ROLLBACK → Tidak ada invalidasi
│
└── HTTP ResponseFormat Cache Key
rf:{project}:{endpoint}:{type}:{identifier}Contoh:
rf:mini-inventory:supplier:datatables:a1b2c3d4
rf:mini-inventory:supplier:read:e5f6g7h8
rf:mini-inventory:supplier:lookup_static:allCache pada Processor
Processor dapat memanfaatkan cache melalui konfigurasi cache di file payload JSON:
{
"name": "stock-card",
"method": "POST",
"cache": {
"enabled": true,
"ttl": 300,
"invalidates": ["stock_inbound", "stock_outbound", "item_product"]
}
}| Property | Tipe | Keterangan |
|---|---|---|
cache.enabled | boolean | Aktifkan cache untuk processor ini |
cache.ttl | number | TTL dalam detik (override global CACHE_TTL) |
cache.invalidates | string[] | Daftar nama endpoint CRUD yang memicu invalidasi cache processor ini |
Array invalidates berisi nama-nama endpoint CRUD. Saat salah satu endpoint tersebut melakukan operasi WRITE, cache processor ini ikut ter-invalidasi. Contoh: jika ada INSERT di endpoint stock-inbound, cache processor stock-card otomatis dihapus.
File processor tidak perlu dimodifikasi karena cache handling sepenuhnya ditangani oleh router yang di-generate. Generator juga memiliki mutation guard yang otomatis mengabaikan cache.enabled pada processor bertipe mutasi (PUT/DELETE atau SQL mengandung INSERT/UPDATE/DELETE).
Graceful Degradation
Cache dirancang dengan prinsip non-blocking. Kegagalan cache tidak mengganggu operasi utama.
| Skenario | Perilaku |
|---|---|
| Redis tidak tersedia saat startup | Server berhenti dengan error message |
| Redis terputus saat runtime | Cache GET return null, request langsung ke database |
| Cache SET error | Diabaikan, response tetap dikirim ke client |
| Registry population error | Cascade invalidation di-skip, cache expire via TTL |
Monitoring dan Debugging
Log Messages
| Event | Level | Keterangan |
|---|---|---|
cache_hit | info | Data ditemukan di cache |
cache_miss | info | Data tidak ada di cache, query ke database |
cache_set | info | Data disimpan ke cache |
cache_invalidate_pattern | info | Cache di-invalidasi setelah operasi WRITE |
Redis CLI
# Lihat semua cache key untuk satu endpoint
redis-cli -p 6380 KEYS "rf:mini-inventory:supplier:*"
# Cek sisa TTL
redis-cli -p 6380 TTL "rf:mini-inventory:supplier:datatables:a1b2c3d4"
# Hapus semua cache satu endpoint
redis-cli -p 6380 --scan --pattern "rf:mini-inventory:supplier:*" | xargs redis-cli -p 6380 DELPanduan TTL (TTL Guide)
| TTL | Skenario | Trade-off |
|---|---|---|
| 60 detik | Data sering berubah, freshness prioritas | Hit rate lebih rendah |
| 300 detik (default) | Keseimbangan freshness dan performa | Cocok untuk sebagian besar kasus |
| 1800 detik | Data stabil, performa prioritas | Data bisa stale sampai 30 menit |
| 3600 detik | Data hampir tidak pernah berubah | Cocok untuk data referensi/master |
Langkah Selanjutnya (Next Steps)
- Distributed Lock untuk koordinasi write antar worker
- Idempotency untuk proteksi duplikasi request
- Rate Limit untuk pembatasan jumlah request