Instagram Jobs
Jobs für Instagram-spezifische Verarbeitung. Instagram-Scraping selbst läuft über das Collector-System (Browser-Extension), nicht über Laravel Queues.
ProcessWatcherImportRun
Dispatcht einzelne ImportWatcherFromUrl Jobs für jedes Item eines Bulk-Imports. Fungiert als Dispatcher-Job, um N+1-Probleme in Web-Requests zu vermeiden.
Location: app/Jobs/ProcessWatcherImportRun.php
| Eigenschaft | Wert |
|---|---|
| Queue | imports-youtube |
| Tries | 1 |
| Timeout | 300s (5 Minuten für große Imports) |
| Unique | Nein |
| Trigger | User-Import (Livewire Watchers\Index) |
Ablauf
WatcherImportRunladen und validieren- Alle
WatcherImportItemRecords für diesen Run abfragen - Pro Item einen
ImportWatcherFromUrlJob dispatchen (aufimports-youtubeQueue)
foreach ($items as $item) {
ImportWatcherFromUrl::dispatch(
runId: $this->runId,
workspaceId: $run->workspace_id,
createdBy: $run->created_by,
url: $item->url,
dedupeKey: $item->dedupe_key,
)->onQueue('imports-youtube');
}
Zusammenspiel mit Import-System
User gibt URLs ein (Livewire)
└── WatcherImportRun + WatcherImportItems erstellen
└── ProcessWatcherImportRun dispatchen
└── Pro Item: ImportWatcherFromUrl dispatchen
├── Profil importieren (API-Call)
├── Watcher + WatcherSource erstellen
├── WatcherImportProgress broadcasten
└── Bei Quota: Run pausieren, Jobs verzögern
FindRelatedInstagramProfiles
Sucht ähnliche Instagram-Profile basierend auf Keyword-Matching aus der lokalen Datenbank. Keine API-Calls erforderlich.
Location: app/Jobs/Instagram/FindRelatedInstagramProfiles.php
| Eigenschaft | Wert |
|---|---|
| Queue | instagram-related-profiles |
| Tries | 3 |
| Backoff | 1min, 5min, 15min |
| Unique | Ja (uniqueFor: 3600, 1 Stunde) |
| UniqueId | find-related-instagram-profiles-{socialProfileId} |
| Trigger | User-Klick (Livewire RelatedProfiles) |
Ablauf
- Profil laden, Status auf
runningsetzen - Keywords extrahieren (
ProfileKeywordExtractor): Bio, Handle, Username - Kandidat-Profile mit gemeinsamen Keywords finden (max 500)
- Relevance-Scores berechnen (max 100 Punkte)
- Top 25 Profile speichern in
instagram_related_profiles RelatedProfilesCalculatedEvent broadcasten
Keyword-Extraktion + AI-Keywords
Der ProfileKeywordExtractor Service extrahiert Keywords aus mehreren Quellen. Zusaetzlich werden Gemini AI-Keywords (ai_keywords JSONB) hinzugemerged:
$keywords = $extractor->extractAndStore($profile);
// Quellen: bio, handle, username
// + AI Keywords aus $profile->ai_keywords
$aiKeywords = ! empty($profile->ai_keywords) ? $profile->ai_keywords : [];
$allKeywords = array_unique(array_merge($localKeywords, $aiKeywords));
Dynamische Stopwords aus keywords:update-stopwords werden automatisch gefiltert.
Source-gewichtete Keyword-Scoring
Keywords werden nach Herkunft unterschiedlich gewichtet:
| Source | Punkte pro Match | Begruendung |
|---|---|---|
bio | 6 | Bio-Inhalt ist am aussagekraeftigsten |
title | 5 | Display-Name zeigt Thema |
handle | 3 | Handle-Woerter sind weniger spezifisch |
| Default | 4 | Fallback fuer unbekannte Sources |
Relevance-Scoring (max 100 Punkte)
| Kriterium | Punkte | Beschreibung |
|---|---|---|
| Parsed Link Match | 0-30 | Approved (30pt), auto-parsed (25pt), generic @handle (20pt) |
| Popularity Bonus | 0-20 | Absolute Follower-Zahl (1M+ = 20 Punkte) |
| Bio-Keyword-Match | variabel | Source-gewichtet (bio=6, title=5, handle=3 pro Match) |
| Follower-Aehnlichkeit | 0-15 | Logarithmische log10-Skala |
| Favorites-Bonus | 0-10 | Konfigurierbar via config('postbox.favorites_tiers_instagram') |
| Name-Aehnlichkeit | 0-10 | similar_text() auf Profil-Titel |
| Gleicher Profile-Typ | 0-10 | Business/Creator/Private Match |
| Sprache/Land | 0-10 | +5 gleiche Sprache, +5 gleiches Land |
Minimum-Schwelle: MIN_RELEVANCE_SCORE = 15 — Kandidaten darunter werden verworfen.
Parsed Link Score
Links aus social_profile_links werden batch-geladen ($approvedLinksByProfile) und beruecksichtigt:
// Approved curated Link: 30 Punkte
// Auto-parsed (unapproved) Link: 25 Punkte
// Generischer @handle in Bio: 20 Punkte
Fehlerbehandlung
- Status wird auf
failedgesetzt mit Fehlerbeschreibung - Error-Report via
report()mit Profil-Kontext RelatedProfilesCalculatedEvent mit Fehler-Status broadcasten- Bei fehlenden Keywords: Bestehende Related Profiles werden gelöscht, Status
completed
RecalculateRelatedInstagramScores
Berechnet Relevance-Scores für bestehende Instagram Related Profiles neu, basierend auf aktuellen Follower-Daten. Keine neue Keyword-Suche.
Location: app/Jobs/Instagram/RecalculateRelatedInstagramScores.php
| Eigenschaft | Wert |
|---|---|
| Queue | instagram-related-profiles |
| Tries | 1 |
| Timeout | 120s |
| Unique | Nein |
| Trigger | social:recalculate-related-scores Command |
Scoring (max 100 Punkte)
| Kriterium | Punkte | Beschreibung |
|---|---|---|
| Base (existierende Beziehung) | 25 | Grundpunkte für jede Beziehung |
| Popularity Bonus | 0-25 | Follower-basiert (1M+ = 25) |
| Follower-Ähnlichkeit | 0-15 | log10-Skala-Vergleich |
| Name-Ähnlichkeit | 0-15 | similar_text() Vergleich |
| Gleicher Profile-Typ | 0-10 | Business/Creator/Private |
| Sprache/Land | 0-10 | +5 Sprache, +5 Land |
Ablauf
- Source-Profil und alle Related Profiles laden (mit Eager Loading)
- Follower-Counts fuer alle betroffenen Profile aus
social_profile_daily_metricsabfragen - Neuen Score pro Beziehung berechnen
- Batch-Update via CASE/WHEN SQL (eine Query statt N einzelner UPDATEs)
- Anzahl aktualisierter Scores loggen
Batch-Update
UPDATE instagram_related_profiles
SET relevance_score = (CASE WHEN id = ? THEN ? ... END)::smallint, updated_at = ?
WHERE id IN (?, ...)