Zum Hauptinhalt springen

YouTube API Quota

Multi-Key-Pool-System mit automatischem Failover, Exhaustion-Caching und Recovery fuer die YouTube Data API v3.

Key Pool System

Der YouTubeDataApiClient verwaltet mehrere API-Key-Pools mit einer definierten Failover-Kaskade. Jeder Pool hat eine eigene Prioritaetsreihenfolge, faellt aber automatisch auf die allgemeinen Keys zurueck.

Failover-Kaskade

Pool 'video':    YOUTUBE_API_VIDEO_KEYS -> YOUTUBE_API_EXTENDED_KEYS -> YOUTUBE_API_KEYS -> YOUTUBE_API_KEY
Pool 'research': YOUTUBE_API_RESEARCH_KEYS -> YOUTUBE_API_KEYS -> YOUTUBE_API_KEY
Pool 'default': YOUTUBE_API_KEYS -> YOUTUBE_API_KEY

Keys werden automatisch dedupliziert -- ein Key der in mehreren Pools vorkommt, wird nur einmal pro Kaskade versucht.

Pool-Zuordnung

PoolVerwendungPrimary Keys
defaultChannel-Import, Daily Scrape, allgemeine AbfragenYOUTUBE_API_KEYS
videoVideo-Sync (playlistItems, videos.list)YOUTUBE_API_VIDEO_KEYS
researchRelated Channels Suche (search.list)YOUTUBE_API_RESEARCH_KEYS
extendedLegacy-PoolYOUTUBE_API_EXTENDED_KEYS

Location: app/Services/Social/YouTube/YouTubeDataApiClient.php (Methode keysForPool())

Key Rotation Engine

Die Rotation arbeitet mit einem Two-Pass-Ansatz:

Pass 1: Nicht-erschoepfte Keys durchprobieren

fuer jeden Key im Pool:
- Skip falls Key im Exhaustion-Cache liegt
- API-Request ausfuehren
- Bei Erfolg: Key verwenden, fertig
- Bei Quota/Rate-Limit-Fehler: Key als exhausted markieren, naechsten Key versuchen
- Bei anderem Fehler: sofort Exception werfen

Pass 2: Recovery-Versuch

falls alle Keys exhausted:
- 3 Sekunden warten (RECOVERY_DELAY_SECONDS)
- Keys erneut versuchen die in DIESEM Call exhausted wurden
- Rate-Limits erholen sich oft innerhalb von Sekunden
- Bei Erfolg: Exhaustion-Cache fuer diesen Key loeschen

Exhaustion-Cache

Erschoepfte Keys werden im Redis-Cache markiert, damit nachfolgende Requests sie ueberspringen:

FehlertypCache TTLGrund
quotaExceeded, dailyLimitExceededBis Mitternacht PT + 5 Min (min 30 Min)Tages-Quota erholt sich erst um Mitternacht Pacific Time
rateLimitExceeded, userRateLimitExceeded5 MinutenRate-Limits erholen sich schnell
// Cache-Key-Format
'yt_key_exhausted:{pool}:{md5_prefix_8chars}'

Location: app/Services/Social/YouTube/YouTubeDataApiClient.php (Methoden markKeyExhausted(), isKeyExhausted(), clearKeyExhausted())

Circuit Breaker

Der YouTubeQuotaGuard implementiert einen Circuit-Breaker pro Pool, der API-Calls blockiert wenn alle Keys erschoepft sind.

Ablauf

  1. canMakeCall($pool) prueft zuerst den Circuit Breaker (guenstig, pool-weit)
  2. Wenn Circuit Breaker offen → pruefe ob einzelne Keys recovered sind
  3. Wenn ein Key recovered → Circuit Breaker schliessen, Call erlauben
  4. Wenn kein Key recovered → Call blockieren

Circuit Breaker TTL

AusloeserTTLBeschreibung
Daily Quota ExhaustionBis Mitternacht PT + 5 Min (min 30 Min)Dynamisch berechnet via secondsUntilQuotaReset()
Rate Limit5 MinutenKeys erholen sich schnell

TTL-Berechnung (Mitternacht Pacific Time)

YouTube-Quotas resetten um Mitternacht Pacific Time (UTC 08:00 PST / UTC 07:00 PDT). Die TTL wird berechnet als endOfDay('America/Los_Angeles') + 6 Minuten, mit einem Safety Floor von 30 Minuten.

// Cache-Key-Format
'yt_pool_circuit_breaker:{pool}'

Location: app/Services/Social/YouTube/YouTubeQuotaGuard.php

Video-Sync (Full-Sync)

Der Video-Sync fuehrt taeglich einen vollstaendigen Playlist-Fetch durch (14:00 UTC). Delta-Sync-Spalten (last_seen_video_id, last_video_count etc.) wurden entfernt und durch einen einfacheren Full-Sync-Ansatz ersetzt.

Neue Videos werden primaer durch WebSub Push-Notifications und RSS-Feed-Polling erkannt (0 API-Quota). Der taeglich Full-Sync gleicht lediglich Statistiken ab.

Quota-Kosten pro Operation

OperationEndpointQuota-Kosten
Channel abrufenchannels.list1 Unit
Playlist-ItemsplaylistItems.list1 Unit
Video-Detailsvideos.list1 Unit
Channel-Suchesearch.list100 Units

Das taegliche Quota-Limit pro Projekt betraegt standardmaessig 10.000 Units. Ein einzelner search.list-Call verbraucht somit 1% des Tagesbudgets.

Typische Kosten-Szenarien

SzenarioUnits pro Profil
Daily Scrape (Channel-Refresh)1 Unit
Video Full-Sync (taeglich, bekannte Videos)2-3 Units
Video Full-Sync (mit neuen Videos)3-4 Units
Related Channels Suche100-500 Units

Error-Benachrichtigung bei Final Fallback

Wenn die Kaskade auf den letzten Key (YOUTUBE_API_KEY) zurueckfaellt, wird ein Error-Report ausgeloest:

report(new RuntimeException(
"YouTube API Quota exhausted for pool '{$pool}', falling back to YOUTUBE_API_KEY"
));

Rate-Limited auf 1x pro Stunde pro Pool via Cache-Key youtube_api_fallback_notified:{pool}.

Location: app/Services/Social/YouTube/YouTubeDataApiClient.php (Methode notifyIfFinalFallback())

Research Quota Service

Der ResearchQuotaService prueft die verfuegbare Quota fuer postbox-research-* Projekte, bevor Auto-Fill-Jobs gestartet werden.

$service = app(ResearchQuotaService::class);

$status = $service->getStatus();
// -> ['used' => 4500, 'limit' => 10000, 'remaining' => 5500, 'percent_available' => 55.0, ...]

$service->allowsAutoFill(); // true wenn >= 25% verfuegbar
  • Gecached fuer 5 Minuten
  • Aggregiert Quota ueber alle postbox-research-* Projekte
  • Liest aus google_api_quota_limits und google_api_quota_usages Tabellen

Location: app/Services/YouTube/ResearchQuotaService.php

Connection Retry

Der HTTP-Client implementiert Retry-Logik fuer Verbindungsfehler (SSL-Timeouts, Connection-Resets):

  • Max 3 Versuche
  • Exponential Backoff: 2s, 4s, 8s
  • Timeout: 30s Request, 15s Connect
  • Nur bei ConnectionException (nicht bei API-Fehlern)

.env Variablen

VariableDefaultBeschreibung
YOUTUBE_API_KEY--Single Fallback Key (letzte Kaskadenstufe)
YOUTUBE_API_KEYS--General Pool, kommasepariert
YOUTUBE_API_EXTENDED_KEYS--Extended Pool (Legacy), kommasepariert
YOUTUBE_API_VIDEO_KEYS--Dedizierter Pool fuer Video-Sync
YOUTUBE_API_RESEARCH_KEYS--Dedizierter Pool fuer Related Channels / search.list

Alle Key-Variablen akzeptieren kommaseparierte Listen (AIza...,AIza...,AIza...).