Maliyet Karşılaştırması
Storage Zone ek maliyeti sadece ~$3/ay, ama kod değişikliği ve migration gerektirir.
Mevcut Sistem Mimarisi
HLS Dönüşüm Akışı
Dosya Yapısı
storage/tenant1001/app/public/muzibu/
├── songs/ # Orijinal dosyalar
│ ├── song_xxx.mp3
│ ├── mp3_128/ # Fallback 128k
│ │ └── {song_id}.mp3
│ └── mp3_64/ # Fallback 64k
│ └── {song_id}.mp3
└── hls/ # HLS Streaming
└── {song_id}/
├── playlist.m3u8 # Ana playlist
├── master.m3u8 # ABR master
├── segment-*.ts # 4sn chunk'lar
├── enc.bin # AES-128 key
├── ultralow/ # 32 kbps
├── low/ # 64 kbps
└── mid/ # 128 kbps
Dosya Boyutları (Per Song)
Değişecek Dosyalar (8 Dosya)
Modules/Muzibu/App/Jobs/ConvertToHLSJob.php
HLS dönüşümü sonrası dosyaları Bunny'e yükleyecek şekilde güncelle.
// MEVCUT: Sadece local storage'a yazıyor
$hlsPath = $this->convertToHLS($song);
// YENİ: Local + Bunny'e yaz
$hlsPath = $this->convertToHLS($song);
app(BunnyStorageService::class)->uploadDirectory(
$localHlsPath,
"hls/{$song->song_id}"
);
app/Services/Muzibu/HLSService.php
MP3 fallback üretimi sonrası Bunny'e yükleme ekle.
// generateMp3() fonksiyonuna ekle:
public function generateMp3($song, $bitrate)
{
// Mevcut FFmpeg kodu...
// YENİ: Bunny'e de yükle
if (config('services.bunny.enabled')) {
app(BunnyStorageService::class)->upload(
$localPath,
"songs/mp3_{$bitrate}/{$song->song_id}.mp3"
);
}
}
Modules/Muzibu/App/Observers/SongObserver.php
forceDeleted() event'inde Bunny'den de silme ekle.
protected function cleanupAudioFiles(Song $song): void
{
// Mevcut local silme kodu...
// YENİ: Bunny'den de sil
if (config('services.bunny.enabled')) {
$bunny = app(BunnyStorageService::class);
$bunny->deleteDirectory("hls/{$song->song_id}");
$bunny->delete("songs/mp3_128/{$song->song_id}.mp3");
$bunny->delete("songs/mp3_64/{$song->song_id}.mp3");
}
}
Modules/Muzibu/App/Http/Controllers/Api/SongStreamController.php
Stream endpoint'inde Bunny CDN URL'lerini döndür.
// stream() response'unda URL'leri değiştir:
// MEVCUT
'hls' => "/storage/tenant1001/public/muzibu/hls/{$id}/master.m3u8"
// YENİ (Bunny aktifse)
'hls' => config('services.bunny.enabled')
? "https://muzibu-audio.b-cdn.net/hls/{$id}/master.m3u8"
: "/storage/tenant1001/public/muzibu/hls/{$id}/master.m3u8"
Modules/Muzibu/App/Http/Livewire/Admin/SongManageComponent.php
Orijinal dosya upload'ında Bunny'e de yükle (opsiyonel).
public function updatedAudioFile()
{
// Mevcut validasyon ve local kayıt...
// YENİ: Orijinal dosyayı da Bunny'e yükle
if (config('services.bunny.upload_originals')) {
app(BunnyStorageService::class)->upload(
$this->audioFile->getRealPath(),
"songs/originals/{$filename}"
);
}
}
Modules/Muzibu/App/Models/Song.php
getHlsUrl() ve benzeri metodlarda Bunny URL desteği.
public function getHlsUrl(): ?string
{
if (!$this->hls_path) return null;
// YENİ: Bunny URL kontrolü
if (config('services.bunny.enabled')) {
return config('services.bunny.cdn_url') . '/' . $this->hls_path;
}
return $this->getStorageUrl($this->hls_path);
}
config/filesystems.php
Bunny Storage disk driver'ı ekle.
'disks' => [
// Mevcut diskler...
'bunny' => [
'driver' => 'bunny',
'api_key' => env('BUNNY_STORAGE_API_KEY'),
'storage_zone' => env('BUNNY_STORAGE_ZONE'),
'region' => env('BUNNY_STORAGE_REGION', 'de'),
],
],
config/services.php
Bunny servis ayarları.
'bunny' => [
'enabled' => env('BUNNY_STORAGE_ENABLED', false),
'api_key' => env('BUNNY_STORAGE_API_KEY'),
'storage_zone' => env('BUNNY_STORAGE_ZONE'),
'cdn_url' => env('BUNNY_CDN_URL'),
'upload_originals' => env('BUNNY_UPLOAD_ORIGINALS', false),
],
Yeni Oluşturulacak Dosyalar (3 Dosya)
app/Services/Bunny/BunnyStorageService.php
Bunny Storage API wrapper servisi.
class BunnyStorageService
{
public function upload($localPath, $remotePath): bool;
public function uploadDirectory($localDir, $remoteDir): bool;
public function delete($remotePath): bool;
public function deleteDirectory($remoteDir): bool;
public function exists($remotePath): bool;
public function getUrl($remotePath): string;
}
app/Console/Commands/MigrateToBunnyCommand.php
Mevcut dosyaları Bunny'e migrate eden artisan komutu.
// Kullanım:
php artisan muzibu:migrate-to-bunny --all # Tüm şarkılar
php artisan muzibu:migrate-to-bunny --song=123 # Tek şarkı
php artisan muzibu:migrate-to-bunny --chunk=100 # 100'lük gruplar
php artisan muzibu:migrate-to-bunny --dry-run # Test modu
app/Providers/BunnyServiceProvider.php
Bunny servislerini register eden provider.
class BunnyServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(BunnyStorageService::class);
}
public function boot()
{
// Custom filesystem driver
Storage::extend('bunny', function($app, $config) {
return new BunnyStorageAdapter($config);
});
}
}
Yeni ENV Değişkenleri
# Bunny Storage Zone
BUNNY_STORAGE_ENABLED=false
BUNNY_STORAGE_API_KEY=your-storage-api-key
BUNNY_STORAGE_ZONE=muzibu-audio
BUNNY_STORAGE_REGION=de
# Bunny CDN (Pull Zone)
BUNNY_CDN_URL=https://muzibu-audio.b-cdn.net
# Migration Options
BUNNY_UPLOAD_ORIGINALS=false
BUNNY_FALLBACK_TO_LOCAL=true
Migration Stratejisi
Hazırlık (Gün 1)
- Bunny Storage Zone oluştur
- API key al
- BunnyStorageService kodunu yaz
- ENV değişkenlerini ekle
Dual-Write Modu (Gün 1-2)
- ConvertToHLSJob'u güncelle (local + Bunny)
- HLSService MP3 fallback'ları güncelle
- SongObserver silme işlemlerini güncelle
- Test: Yeni şarkı yükle, Bunny'de görün
Batch Migration (Gün 2-3)
- MigrateToBunnyCommand yaz
- --dry-run ile test et
- Chunk chunk migrate et (100'lük gruplar)
- ~280 GB transfer (~4-8 saat)
Cutover (Gün 3)
- SongStreamController URL'leri Bunny'e çevir
- BUNNY_STORAGE_ENABLED=true yap
- Cache temizle
- Test: Şarkı çal, Bunny'den geldiğini doğrula
Cleanup (1 Hafta Sonra)
- 1 hafta Bunny'den sorunsuz servis et
- Local HLS dosyalarını sil (disk alanı kazan)
- BUNNY_FALLBACK_TO_LOCAL=false yap
Risk Analizi
Riskler
- Migration süresi: 280GB transfer 4-8 saat sürebilir
- Bunny kesintisi: Bunny down olursa müzik çalmaz
- API key güvenliği: Storage API key sızarsa dosyalar risk altında
- Encryption key: enc.bin dosyaları public olur mu?
Çözümler
- Fallback: BUNNY_FALLBACK_TO_LOCAL=true ile local'e düş
- Parallel: İlk hafta hem local hem Bunny aktif tut
- Token auth: Bunny Token Authentication aktif et
- Key endpoint: enc.bin yerine /hls-key/ endpoint kullan
Sonuç ve Öneri
Storage Zone EKLERSEN:
- Origin sunucuya 0 yük
- Daha az donma riski
- Aylık +$3 (280GB)
- 2-3 gün kod yazma
- 280GB migration
Storage Zone EKLEMEZSEN:
- Kod değişikliği yok
- Hemen DNS geçişi yapılabilir
- Origin Shield + Burrow yeterli
- Cache miss'te origin'e istek
Önerim: Önce Pull Zone ile DNS geçişi yap. 1 ay kullan, Bunny Statistics'ten cache HIT oranını gör. Eğer %90+ ise Storage Zone gereksiz. Origin yükü hala yüksekse o zaman Storage Zone ekleriz.