SADECE Tenant 1001 (muzibu.com) için aktif!
- Users tablosu universal (tüm tenant'lar paylaşır)
- Premium alanlar sadece ilişki: is_premium, trial_ends_at, daily_listening_seconds
- Diğer tenant'lar bu sistem etkilenmez
✓ Guest kullanıcılar her şarkının ilk 30 saniyesini dinleyebilir
✓ "Reklamsız" ve "Offline indirme" özellikler kaldırıldı
✓ Deneme süresi geri sayım olarak gösteriliyor
✓ Admin panel tenant 1001'e özel kolonlarla gösteriliyor
✓ Performans optimizasyonları eklendi (Redis, Cache, Lazy Reset)
Fade-out: 25. saniyede volume 1.0'dan 0.0'a 5 saniyede linear geçiş
Modal tetik: 30. saniyede Howler onEnd event
Kontrol: !auth()->check() ? preview mode : full mode
Component: Mevcut auth modal sistemi kullanılacak
Kontrol: Her şarkı başlamadan önce API'den user.daily_listening_seconds kontrol
Limit: 3600 saniye (1 saat)
Reset: Lazy reset (kullanıcı çalarken last_listen_reset < today() kontrolü)
Modal tetik: Player play() fonksiyonu içinde kontrolle engelleme
// UserManageComponent.php
if (tenant()->id == 1001) {
$this->columns[] = 'membership_type';
$this->columns[] = 'daily_listening';
$this->bulkActions[] = 'make_premium';
$this->bulkActions[] = 'give_trial_7';
}
| Kullanıcı | E-posta | 🎵 Üyelik Tipi | ⏱️ Bugün Dinleme | İşlemler | |
|---|---|---|---|---|---|
| Ahmet Yılmaz | ahmet@example.com | 👤 Normal Üye | 42 dk / 60 dk | ||
| Mehmet Demir | mehmet@example.com | 💎 Premium | Sınırsız | ||
| Ayşe Kaya | ayse@example.com | 🎁 Deneme (5 gün) | Sınırsız | ||
| Zeynep Şahin | zeynep@example.com | 👤 Normal Üye | 60 dk / 60 dk (DOLDU) |
Universal Users Tablosu:
- is_premium (boolean)
- trial_ends_at (timestamp)
- daily_listening_seconds (integer)
- last_listen_reset (date)
Diğer Tenant'lar: Bu kolonları görmez, etkilenmez
| İşlem | Sorun |
| Her şarkı başlamadan API call | N+1 problem, DB yükü |
| Her saniye dinleme artırma | DB'ye sürekli write |
| Günlük reset (tüm kullanıcılar) | 00:00'da DB lock |
| user_listening_logs tablosu | Hızlı şişme (milyon satır) |
// Her API call'da user bilgisi cache'den
$userAccess = Cache::remember("user_access_{$userId}", 300, function() {
return [
'is_premium' => $user->isPremium(),
'daily_listening_seconds' => $user->daily_listening_seconds,
'limit' => 3600
];
});
// Frontend: Her timeupdate'de Redis'e yaz
Redis::hincrby("listening:{$userId}", date('Y-m-d'), $seconds);
// Background job: Her 10 saniyede DB'ye flush
$dailySeconds = Redis::hget("listening:{$userId}", date('Y-m-d'));
User::where('id', $userId)->update(['daily_listening_seconds' => $dailySeconds]);
// Kullanıcı şarkı çalarken kontrol:
if ($user->last_listen_reset < today()) {
$user->update([
'daily_listening_seconds' => 0,
'last_listen_reset' => today()
]);
Cache::forget("user_access_{$userId}");
}
// Migration: Aylık partitioning
CREATE TABLE user_listening_logs (
id BIGINT AUTO_INCREMENT,
user_id BIGINT,
song_id BIGINT,
listened_seconds INT,
listened_at TIMESTAMP,
PRIMARY KEY (id, listened_at)
) PARTITION BY RANGE (YEAR(listened_at) * 100 + MONTH(listened_at)) (
PARTITION p202511 VALUES LESS THAN (202512),
PARTITION p202512 VALUES LESS THAN (202601)
);
// Cron: 90 günden eski logları sil
DB::table('user_listening_logs')
->where('listened_at', '<', now()->subDays(90))
->delete();
| Metrik | Hedef | Optimizasyon |
| API Response Time | < 50ms | Cache (5 dk) |
| DB Write Operations | < 6 per minute | Redis + 10s flush |
| Daily Reset Time | 0ms (no cron) | Lazy reset |
| Logs Table Size | < 10M rows | Partitioning + 90d delete |