Altın Kural
Ödeme Yapan = ANINDA Dinler
Üye olmayan biri ödeme yaptığında 0 saniye gecikme ile müzik dinlemeye başlamalı. Bu noktada cache'lenmiş veri OLMAMALI — taze kontrol yapılmalı.
Çözüm: Ödeme onayı geldiğinde cache ANINDA temizlenir (bust)
Süresi Biten = 1-2 Saat Tolerans
Üyeliği biten bir kullanıcı 1-2 saat fazladan dinlerse sorun olmaz. Bu tolerans, cache süresini uzatmamıza ve sunucu yükünü dramatik şekilde düşürmemize olanak sağlar.
Çözüm: isPremium cache'i 2 saat — süresi biten max 2 saat fazla dinler
Bu İş Mantığı Neyi Mümkün Kılıyor?
Ödeme → Erişim Zinciri (Şu An)
Ödeme yapıldığında sunucuda neler oluyor — bu zinciri anlamak cache stratejisinin temelidir.
PayTR ödeme onayı gelir (callback)
POST /api/payment-callback → hash doğrulama
Sipariş aktifleşir, abonelik oluşur
Order::activateSubscriptionItems() → Subscription oluştur/güncelle
SubscriptionObserver tetiklenir
Subscription::rechainUserSubscriptions() → tarih zinciri yeniden hesaplanır
users.subscription_expires_at güncellenir
User::recalculateSubscriptionExpiry() → Tüm aboneliklerin en son bitiş tarihi yazılır
Cache BUST — isPremium cache'i ANINDA temizlenir
YENİ EKLENECEK → recalculateSubscriptionExpiry() içinde Redis::forget("user:{id}:is_premium")
Kullanıcı şarkı çalar → isPremium() = taze sorgu → cache'e yaz (2 saat)
İlk istek DB'ye gider, sonraki 2 saat boyunca cache'den döner
Basit anlatım: Ödeme geldiğinde sistem zaten otomatik olarak subscription tablosunu ve users tablosunu güncelliyor. Tek yapmamız gereken: bu güncelleme anında cache'i de temizlemek. Sonraki şarkı çalma isteği taze DB'den okur ve "premium" olarak cache'ler.
Tüm API Endpoint'leri — Frekans & Cache Haritası
Yüksek = Her şarkıda Orta = Sayfa/oturum bazlı Düşük = Nadiren
Şu an: Cache yok | Öneri: Cache eklenecek
Her Şarkıda Çağrılan (Kritik Yol)
Kullanıcı her şarkıyı çaldığında bu endpoint'ler sırayla tetiklenir. En çok optimize edilmesi gereken grup.
/api/muzibu/songs/{id}/stream
Premium kontrolü + stream URL oluşturma + şifreleme
- ● isPremium() → her seferinde taze DB sorgusu
- ● Şarkı verisi → Redis 24 saat (iyi)
- ● URL imzalama → her seferinde hesaplanıyor
- ● isPremium() → Redis 2 saat (ödeme anında bust)
- ● Şarkı verisi → Redis 24 saat (değişmez)
- ● URL imzalama → her seferinde (güvenlik gereği)
Kazanç: ~30-50ms/istek (DB sorgusu kalkıyor)
/api/muzibu/hls/key/{songId}
HLS şifreleme anahtarı (16 byte binary) — HLS.js otomatik çağırır
- ● Anahtar → Redis 24 saat
- ● Fallback → diskten okuma (enc.bin)
- ● Zaten cache'li — İyi durumda
- ● Soft Mode'da bu istek tamamen kalkar (MP3)
Not: MP3 modunda bu endpoint hiç çağrılmaz — HLS'e özel
/api/muzibu/hls/serve/{songId}/{file}
HLS playlist (m3u8) ve segment (ts) dosyalarını sunar — HLS.js otomatik çağırır
- ● Playlist → her seferinde diskten + regex
- ● Segment → immutable header (CDN friendly)
- ● Playlist şablonu → Redis 24 saat
- ● Soft Mode'da bu istek tamamen kalkar (MP3)
Not: MP3 modunda bu endpoint hiç çağrılmaz — HLS'e özel
/api/muzibu/songs/{id}/track-start
Çalma kaydı oluşturur (Faz 1/3) — 3 DB sorgusu (şarkı kontrol + duplikat kontrol + insert)
- ● await fetch() → player stream başladıktan SONRA
- ● Senkron bekleme (hızı etkilemiyor)
- ● Queue'ya at (Laravel Job)
- ● Anında 200 dön, arka planda yaz
Kazanç: ~100ms (3 DB sorgusu arka plana taşınır)
/api/muzibu/songs/{id}/track-hit
30 saniye dinleme markı (Faz 2/3) — play_count artırır
- ● Zaten setTimeout (30s) ile arka planda
- ● Queue'ya at — play_count Redis'te artır, periyodik DB sync
/api/muzibu/songs/{id}/track-end
Dinleme sonu/atlama kaydı (Faz 3/3) — sendBeacon ile fire-and-forget
- ● Zaten sendBeacon — fire-and-forget, UI bloklamaz
- ● Zaten iyi — opsiyonel queue
Sayfa/Oturum Bazlı Çağrılan
Kullanıcı sayfayı açtığında veya uygulamaya döndüğünde çağrılır. Şarkı başına değil, oturum başına.
/api/muzibu/songs/recent
Son dinlenen şarkılar — 2-3 DB sorgusu, CACHE YOK
- ● Her seferinde 2-3 taze DB sorgusu
- ● JOIN + eager loading + sıralama
- ● Redis 5 dakika (kullanıcı bazlı)
- ● trackStart'ta cache bust (yeni şarkı çalındı)
Kazanç: ~200-400ms (2-3 DB sorgusu tamamen kalkar)
/api/muzibu/songs/popular
Popüler şarkılar — şu an cache YOK (ama 30dk olabilir)
- ● Her seferinde DB sorgusu (play_count sıralaması)
- ● Redis 30 dakika (herkes için aynı)
Kazanç: ~100-300ms + DB yükü azalır (tüm kullanıcılar ortak cache)
/api/muzibu/songs/last-played
Son çalınan şarkı (preload) — şarkı verisi Redis'te, play kaydı DB'de
- ● Şarkı → Redis (24h), play → DB sorgusu
- ● Redis 5 dk (komple yanıt cache)
/api/muzibu/queue/initial
Başlangıç çalma kuyruğu — 2-3 DB sorgusu
- ● Her seferinde taze kuyruk hesaplaması
- ● Redis 10 dakika (kullanıcı bazlı)
Nadiren Çağrılan (Düşük Öncelik)
Kullanıcı gezinirken, arama yaparken çağrılır. Sıklığı düşük, optimizasyon önceliği düşük.
| Endpoint | Ne Zaman | Şu An | Öneri |
|---|---|---|---|
/albums |
Albüm sayfası | Cache yok | Redis 15 dk |
/artists |
Sanatçı sayfası | Cache yok | Redis 15 dk |
/genres |
Tür sayfası | Cache yok | Redis 1 saat |
/playlists |
Playlist sayfası | Cache yok | Redis 10 dk |
/songs/{id} |
Şarkı detayı (queue restore) | Cache yok | Redis 1 saat |
/ratings |
Beğeni/puan | Cache yok | Cache gerekmez (yazma) |
Öncelik Sırası & Beklenen Etki
En çok etki yaratacak değişiklikler önce, en az efor ile en büyük kazanç.
isPremium() Redis Cache (2 Saat)
EN YÜKSEK ETKİ KOLAYHer şarkı çalma isteğinde yapılan DB sorgusu ortadan kalkar. Günde 10.000 şarkı çalınıyorsa = 10.000 DB sorgusu → 0'a düşer.
recent + popular + lastPlayed Cache
ORTA ETKİ KOLAYSayfa açılış hızını dramatik artırır. 3 endpoint birden cache'lenince sayfa yüklenme ~500ms daha hızlı.
Tracking Queue (trackStart arka plana)
ORTA ETKİ ORTA ZORLUKtrackStart 3 DB sorgusu yapıyor. Bunu Laravel Queue'ya taşırsak: API anında 200 döner, DB yazımları arka planda olur. Kullanıcı farkı hissetmez.
HLS Playlist Şablon Cache
HLS KULLANANLAR İÇİNserveHls her çağrıda diskten m3u8 okuyup regex ile URL'leri yeniden yazıyor. Playlist şablonunu Redis'te tutarsak disk I/O + regex overhead kalkar. Not: MP3/Soft Mode'da zaten HLS kullanılmaz — bu optimizasyon sadece HLS kullanıcıları için.
Toplam Etki — Önce vs Sonra
Şarkı Çalma Akışı (Stream Tıkla → Ses Gelir)
| İşlem | Şu An | Cache Sonrası | Soft Mode (MP3) |
|---|---|---|---|
| isPremium kontrolü | ~30-50ms (DB) | ~1ms (Redis) | ~1ms (Redis) |
| Stream URL oluşturma | ~50-100ms | ~50-100ms | ~30-50ms (daha basit) |
| HLS key isteği | ~20-50ms | ~5ms (Redis) | 0ms (gerek yok) |
| HLS playlist isteği | ~100-200ms (disk+regex) | ~10-20ms (Redis) | 0ms (gerek yok) |
| İlk segment/MP3 yükleme | ~100-300ms | ~100-300ms | ~50-150ms (tek dosya) |
| trackStart kaydı | ~50-150ms (await) | ~5ms (queue) | ~5ms (queue) |
| TOPLAM (ses gelene kadar) | ~350-850ms | ~170-430ms | ~85-205ms |
Cache Temizleme (Invalidation) Haritası
Her cache ne zaman temizlenecek — yanlış/eski veri göstermemek için kritik.
| Cache Key | TTL | Ne Zaman Bust? | Tolerans |
|---|---|---|---|
| user:{id}:is_premium | 2 saat | Ödeme onayı, abonelik değişikliği | Biten üye max 2 saat fazla dinler |
| user:{id}:recent_songs | 5 dk | Yeni şarkı çalındığında (trackStart) | 5 dk eski liste görebilir — sorun değil |
| user:{id}:last_played | 5 dk | Yeni şarkı çalındığında (trackStart) | Önceki şarkı preload olur — sorun değil |
| global:popular_songs | 30 dk | TTL ile otomatik yenilenir | 30 dk eski sıralama — sorun değil |
| user:{id}:initial_queue | 10 dk | TTL ile otomatik yenilenir | Kuyruk biraz eski — sorun değil |
| song:{id}:hls_key | 24 saat | Asla (key değişmez) | Key sabit — tolerans gerekmez |
| song:{id}:playlist_tpl | 24 saat | HLS yeniden dönüştürülürse | Playlist sabit — tolerans gerekmez |
Rate Limiting & Sınırlama Stratejisi
Her endpoint'in makul bir çağrı sınırı olmalı — hem kötü niyetli kullanımı önler, hem sunucu korunur.
| Endpoint | Mevcut Limit | Önerilen Limit | Mantık |
|---|---|---|---|
/stream |
throttle.user:stream | 60/saat | Dakikada 1 şarkı = saatte max 60 (gerçekçi) |
/track-start |
Yok | 60/saat | /stream ile aynı oranda (1:1) |
/track-hit |
Yok | 120/saat | 30 saniyede 1 = 3 dakikalık şarkıda 6 hit |
/track-end |
Yok | 60/saat | /stream ile aynı oranda |
/recent |
Yok | 30/saat | Sayfa yenileme sıklığı (cache'le bile korunmalı) |
/popular |
Yok | 30/saat | Global cache'li — sık çağrıya gerek yok |
/hls-key, /hls/serve |
Yok | 120/saat | HLS.js çoklu istek yapar — toleranslı |