Bunny Storage Zone Entegrasyonu

Kod Değişikliği Analizi ve Migration Planı

8 Dosya Değişecek ~280 GB Migration ~2-3 Gün İş
~4,000
HLS Dönüştürülmüş Şarkı
~280 GB
Toplam Dosya Boyutu
8
Değişecek Dosya
3
Yeni Dosya

Maliyet Karşılaştırması

Cloudflare + Argo Mevcut
Pro Plan $25/ay
Argo Base $5/ay
Argo Traffic (8-10TB) $800-1,000/ay
TOPLAM ~$830-1,030/ay
Bunny Pull Zone Kuruldu
Avrupa (%70) $56-70/ay
Ortadoğu (%30) $144-180/ay
Burrow $9.50/ay
TOPLAM ~$210-260/ay
Bunny + Storage Opsiyonel
Pull Zone $210-260/ay
Storage (280GB) +$2.80/ay
Kod Değişikliği Gerekli
TOPLAM ~$215-265/ay
Aylık Tasarruf: $600-800

Storage Zone ek maliyeti sadece ~$3/ay, ama kod değişikliği ve migration gerektirir.

Mevcut Sistem Mimarisi

HLS Dönüşüm Akışı

Admin Upload
ConvertToHLSJob
FFmpeg
Local Storage

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)

Orijinal MP3 5-10 MB
HLS (orijinal kalite) ~22 MB
HLS Variant'lar ~27 MB
MP3 Fallback'lar ~3.5 MB
TOPLAM ~60-70 MB

Değişecek Dosyalar (8 Dosya)

MODIFY Modules/Muzibu/App/Jobs/ConvertToHLSJob.php
Ana HLS Job

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}"
);
MODIFY app/Services/Muzibu/HLSService.php
HLS Teknik İşlemler

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"
        );
    }
}
MODIFY Modules/Muzibu/App/Observers/SongObserver.php
Silme İşlemleri

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");
    }
}
MODIFY Modules/Muzibu/App/Http/Controllers/Api/SongStreamController.php
Playback URL'leri

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"
MODIFY Modules/Muzibu/App/Http/Livewire/Admin/SongManageComponent.php
Upload Handler

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}"
        );
    }
}
MODIFY Modules/Muzibu/App/Models/Song.php
URL Getter'lar

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);
}
MODIFY config/filesystems.php
Disk Tanımı

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'),
    ],
],
MODIFY config/services.php
Servis Config

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)

NEW app/Services/Bunny/BunnyStorageService.php
~150 satır

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;
}
NEW app/Console/Commands/MigrateToBunnyCommand.php
~200 satır

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
NEW app/Providers/BunnyServiceProvider.php
~50 satır

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

1

Hazırlık (Gün 1)

  • Bunny Storage Zone oluştur
  • API key al
  • BunnyStorageService kodunu yaz
  • ENV değişkenlerini ekle
2

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
3

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)
4

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
5

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.