B2B HR-Intelligence SaaS · DACH

VakanzPuls
Projektdokumentation

Umfassende technische und vertriebliche Dokumentation. Alle Metriken werden live von der Plattform geladen.

Version 1.0April 2026
Lade...Aktive Jobs
Lade...E-Mail-Rate
TeamMichael (Tech) · Sandro (Sales/GF)
Live-Daten Letzte Aktualisierung: wird geladen... Jobs/24h: Emails/h: Cluster:
Teil AProdukt & Vertrieb
01
Executive Summary
Produktvision · Live-KPIs

VakanzPuls ist eine B2B HR-Intelligence-Plattform für den DACH-Stellenmarkt. Die Plattform aggregiert Stellenanzeigen, reichert sie mit direkten HR-Kontaktdaten an und gibt Personalvermittlern einen entscheidenden Wettbewerbsvorteil bei der Kundenakquise.

Aktive Stellenanzeigen
E-Mail-Enrichment-Rate
27+
ATS-Systeme integriert
+ 272K Karriereseiten
Kernwert für Personalvermittler: VakanzPuls zeigt in Echtzeit welche Unternehmen gerade aktiv Personal suchen — inklusive direktem Ansprechpartner, Telefonnummer und E-Mail. Kein manuelles Recherchieren mehr. Kein Kaltakquise-Blindflug.

Problem

Personalvermittler verbringen Stunden mit manueller Suche nach Kunden mit offenen Stellen. Kontaktdaten fehlen oder sind veraltet. Der Marktüberblick ist fragmentiert.

Lösung

VakanzPuls crawlt automatisch alle relevanten Job-Quellen im DACH-Raum, reichert Firmen mit direkten HR-Kontaktdaten an und liefert täglich aktuelle Intelligence — vollautomatisch.

ROI

Statt 2–4h täglicher Recherche: 5 Minuten Dashboard-Check. Direkte Kontaktdaten erhöhen Kaltakquise-Erfolgsrate signifikant. Wochenbericht DACH montags 08:00 automatisch.

02
Marktpositionierung
DACH HR-Intelligence — Wettbewerbsvorteile

Der DACH-Stellenmarkt umfasst über 50 Millionen Beschäftigte. Täglich werden zehntausende neue Stellen ausgeschrieben. VakanzPuls ist die erste Plattform die diesen gesamten Markt systematisch aggregiert und für Personalvermittler aufbereitet.

MerkmalVakanzPulsLinkedIn/XingIndeed/StepStoneManuelle Recherche
Echtzeit-Marktdaten✓ Jateilweiseteilweise✗ Nein
Direkte HR-Kontakte✓ automatischmanuell✗ Neinaufwändig
DACH-Vollabdeckung✓ 25+ ATSunvollständigteilweise✗ Nein
Behörden & Sozial✓ 25K+ Stellen✗ Neinteilweise✗ Nein
Outreach-Integration✓ direktInMail (kostenpfl.)✗ Nein✗ Nein
Automatisierungsgrad✓ vollautomatisch✗ manuell✗ manuell✗ manuell
03
Zielgruppe & Anwendungsfälle
Für wen ist VakanzPuls gemacht?
🎯
Personalvermittler & Staffing-Agenturen
Hauptzielgruppe. Benötigen täglich aktuelle Informationen welche Unternehmen gerade Personal suchen — mit direktem Kontakt zum HR-Entscheider.
🏢
HR-Dienstleister & Berater
Unternehmensberater die Mandanten bei Personalthemen unterstützen und einen systematischen Überblick über den Arbeitsmarkt benötigen.
📊
Marktforschung & Analytics
Teams die Stellenmarkt-Trends, Branchen-Entwicklungen und Nachfragesignale für strategische Entscheidungen auswerten.

Typische Anwendungsfälle

Kaltakquise & Neukundengewinnung

Personalvermittler exportieren täglich eine Liste von Unternehmen mit neuen Stellen — inkl. HR-Kontakt-E-Mail. Outreach startet automatisch.

Marktbeobachtung & Frühwarnung

Watchlist-Funktion: Bei neuen Stellen eines Wunschkunden sofortige Telegram-Benachrichtigung. Akquise beginnt bevor der Wettbewerb reagiert.

Branchenanalyse & Wochenbericht

Automatischer DACH-Report jeden Montag: Top-10 Branchen, wachsende Arbeitgeber, Engpassberufe, regionale Hotspots.

Kundenpflege & Bestandsmonitoring

Bestandskunden auf Watchlist — sobald Stellenvolumen sinkt oder neue Positionen entstehen: sofortige Benachrichtigung.

04
Feature-Übersicht
Alle Funktionen der Plattform

Kern-Features (Partner-Dashboard)

🔍
Markt & Quellen
Echtzeit-Übersicht aller aggregierten Job-Quellen. 272K+ Karriereseiten, 27+ ATS-Systeme, Behörden, Hochschulen, Sozialwirtschaft.
Akuter Bedarf
Zeigt Unternehmen mit überdurchschnittlich vielen neuen Stellen in den letzten 7 Tagen — Signale für akuten Personalbedarf.
🔎
Schnelltest
Firma eingeben → sofortiger Steckbrief: E-Mail, Telefon, offene Stellen, Karriereseite, Quality-Score.
👁️
Watchlist
Unternehmen beobachten. Bei neuen Stellenanzeigen sofortiger Telegram-Alert. 7-Tage-Verlauf, Notizen.
📊
DACH-Report
Automatischer Wochenbericht: Top-Branchen, schnellst wachsende Arbeitgeber, regionaler Vergleich DE/AT/CH.
📈
Intelligence
Hiring Signals, Seismograph, Nachfrage-Forecast, Gehaltsanalysen, Engpassberufe-Radar.
🎯
Kundensegmentierung
GVP-Kontakte nach Region, Branche und Score-Tier segmentieren. CSV-Export für gezielte Outreach-Kampagnen.
📧
Outreach-Engine
Automatisierter E-Mail-Versand (SendGrid). 80/Tag, A/B-Templates, Unsubscribe, Tracking. Aktivierung nach Domain.
Quality Score Dashboard
Datenqualität nach Tier (A–F) und Kategorie. Verbesserungspotential identifizieren. Live-Score.
05
Preismodell
SaaS-Abonnement · 3 Tiers · Stripe
Starter
auf Anfrage /Monat
Kleine Personalvermittler & Einzelberater
  • Vollzugriff Markt & Quellen
  • Schnelltest (50/Tag)
  • Watchlist (max. 20 Firmen)
  • DACH-Report wöchentlich
  • E-Mail Support
Enterprise
auf Anfrage /Monat
Große Agenturen & Unternehmensgruppen
  • Alles aus Professional
  • Outreach unbegrenzt
  • Vollständiger API-Zugang
  • Multi-User (5 Seats)
  • White-Label Option
  • Dedizierter Account Manager
  • SLA-Garantie
Status: Stripe technisch integriert. Finale Preise nach Firmengründung und Domain-Aktivierung durch Sandro.
06
DSGVO & Compliance
Datenschutz, Rechtliches, Sicherheit

✓ Umgesetzt

  • Landing Page DSGVO-konform (Cookie-Banner, Datenschutzerklärung)
  • Outreach mit Unsubscribe-Link (DSGVO Art. 17)
  • Opt-out-Verwaltung in Datenbank
  • Datenspeicherung ausschließlich auf EU-Servern (Contabo DE)
  • HTTPS/TLS auf allen Endpunkten

⏳ Ausstehend (nach Gründung)

  • EU-Vertreter Art.27 — DRINGEND
  • Firmenname & Adresse im Impressum
  • datenschutz@vakanzpuls.de (nach Domain)
  • AV-Vertrag Contabo + SendGrid
  • Echte Telefonnummer (Sandro)
Teil BLive-Daten & Metriken
07
Live-Metriken
Direkt von der Plattform · Aktualisiert alle 60s
Aktive Stellenanzeigen
E-Mail-Rate
Mit Telefonnummer
Mit Beschreibung
GMaps-Firmen
Outreach-Kontakte
Bereit für Versand

Quality Score Verteilung

Wird geladen...

Government-Jobs (756K, 65% aller Jobs): government_description_fetcher läuft 4× täglich zur Verbesserung.

08
Datenquellen & Abdeckung
7 aktive Crawling-Systeme · 150K+ Quellen
🔍
ATS-Direktintegration
27+ Applicant-Tracking-Systeme direkt angebunden (inkl. hr4you, talention, coveto). Täglich neue Tenants entdeckt via Batch-Discovery, CDX Internet-Archiv und GMaps-Fingerprinting.
🌐
Karriereseiten-Crawler
120.384 Unternehmenswebsites mit eigenem Stellenbereich. Schema.org, HTML-Parsing, Playwright für JS-intensive Sites.
🏛️
Behörden & Öffentlicher Dienst
Interamt (12.790), Bundesländer-Portale, Niedersachsen, UKM Münster. Insgesamt 25.000+ öffentliche Stellen.
❤️
Sozialwirtschaft
AWO (~6K), DRK (3.961), Caritas (1.322), Malteser (1.243), Volkssolidarität (137). Täglich gecrawlt.
🎓
Hochschulen
Stellenwerk (1.362 Hochschul-Jobs). Akademische und wissenschaftliche Stellen aus deutschen Universitäten.
📰
Zeitungsportale
FAZ, SZ, Zeit via Playwright-Spider. Täglich 06:00 und 15:00 Uhr gecrawlt.
09
ATS-Integration
27+ aktive Applicant-Tracking-Systeme (inkl. hr4you, talention, coveto)
ATS-SystemAktive QuellenJobs (aktiv)MethodeStatus
SmartRecruiters8669.201APIAktiv
Softgarden1.08257.518HTML (LB)Aktiv
Greenhouse90041.409API + WebhookAktiv
Lever86927.588APIAktiv
Personio2.36124.971API + WebhookAktiv
Workday7621.614HTMLAktiv
Workable1.45915.633APIAktiv
iCIMS1637.915HTML (LH)Aktiv
Pinpoint3597.409JSON API (LF)Aktiv
BambooHR1.8736.956JSON API (LD)Aktiv
Breezy5495.376JSON API (LF)Aktiv
Ashby1.4934.272API (LM)Aktiv
Recruitee642.133API (LN)Aktiv
Teamtailor48590HTML (LN)Aktiv
Haufe66553HTML (LN)Aktiv
JOIN.com1.413469API (LN)Aktiv
dvinci28360HTML (LN)Aktiv
hr4you10 (+6)2.256JSON-APINEU 18.04
Talention13 (+10)45Sitemap+JSON-LDNEU 18.04
Coveto15 (+5)86HTML+JSON-LDNEU 18.04
+ Concludis, Schema.org, RSS~600~5.000VerschiedeneAktiv
10
Firmendatenbank (GMaps Discovery)
Wird geladen...
Firmen gesamt
Mit Karriereseite
Vollautomatischer 4-Phasen-Prozess:
1. Query-Generator erzeugt täglich 05:00 neue Such-Kombinationen (v3: 12.271 Queries/Zyklus)
2. gosom-Docker-Container (13 parallel: W1=3, W3=2, W6=8) crawlen Google Maps mit per-Container-Finalisierung
3. GMaps-Reaktor verarbeitet Rohdaten → Firmenprofile (done_1h nach 8-17min)
4. Impressum-Crawler reichert E-Mail, Telefon, Inhaber an
Status 19.04: 595K Discoveries, daemon_keeper via server_caps.json SSOT, Load-Guard 80% vCPU
11
Qualitätsscore-System
Kategorisierte Bewertung · Tägliche Recalculation

ATS / Direkt (Kernformel)

Titel + Location+20 Pkt
Description (>100 Zeichen)+20 Pkt
Employment Type+10 Pkt
E-Mail-Kontakt (Hauptfaktor)+30 Pkt
Telefonnummer+10 Pkt
Karriereseite + Gehalt+10 Pkt
Maximum100 Pkt

Behörden / Sozial (angepasst)

Titel, Location, Description, Emptype+50 Pkt
E-Mail (Bonus, nicht Pflicht)+15 Pkt
Telefonnummer+15 Pkt
PLZ / Adresse vollständig+10 Pkt
Gehaltsangabe (TVöD)+10 Pkt
Maximum100 Pkt

Separate Formel verhindert künstliche Score-Senkung durch Behörden-Jobs.

12
Outreach-Stack
SendGrid · Live-Status
Outreach-Kontakte
Alle mit E-Mail
Status
KomponenteStatusDetails
SendGrid API Key✓ AktivKonfiguriert
E-Mail-Templates A/B✓ FertigDirekt + Frage-Variante
Outreach Engine✓ Fertig80/Tag, Mo–Fr 09:00 Cron
Unsubscribe + Webhook✓ FertigDSGVO-konform
3 Outreach-Segmente✓ BereitStaffing (201) · Mittelstand (384) · Behörden (301)
Domain vakanzpuls.de⏳ SandroNach Ostern → Prompt CP
OUTREACH_ENABLEDfalseAktivierung nach Domain
Teil CTechnische Architektur
13
Systemarchitektur
7-Server-Cluster (Master + 3 Worker + DB-Primary + Scraper + GMaps-dediziert W6) · FastAPI · Next.js · PostgreSQL auf W4 + PgBouncer
VakanzPuls — Systemarchitektur (Stand: 19.04.2026) 7-Server-Cluster · 43+ Daemons · 1.41M aktive Jobs · 18 MVs · 200+ API-Endpoints · PostgreSQL auf W4 Admin :3003 Portal :3001 Landing :3010 Monitor Doku Master · 161.97.79.192 Backend :8003 · Orchestrator · Celery Beat · Telegram Bot · Auto-Analyst · 47 Crons FastAPI :8003 PgBouncer :5433 Advertsdata (5W) Heartbeat Nginx+SSL W4 — PostgreSQL Primary · 5.189.174.152 48GB RAM · PgBouncer :5433 (pool_size 80) · 18 MVs · 80+ Tabellen · Backup 03:00 KEIN Scraper · KEINE Daemons — nur Datenbank Worker-1 173.212.217.37 ATS · Enrichment · Quality Shadow-Mon · AD(8W) Worker-2 161.97.170.205 Career · Triple · BA-Fetcher Domain-Resolver · AD(8W) Worker-3 95.111.233.0 · 47GB Desc-Shards · Career · Booster Heartbeat · AD(12W) Worker-5 (Scraper) 173.212.253.115 Advertsdata dediziert (12W) Desc-Shards 5-7 · Playwright Worker-6 (GMaps) 164.68.123.85 · 16 vCPU / 62 GB GMaps 25 Docker-Container gmaps-daemon · gosom-scraper Master (API + Daemons) W4 (DB Primary) W1-W3 (Scraping + Enrichment) W5 (Advertsdata dediziert) W6 (GMaps dediziert)

Tech-Stack

Backend
FastAPI
Python 3.12
Uvicorn
Celery
aiohttp
Playwright
Frontend
Next.js 14
React 18
TypeScript
App Router
Lucide Icons
Datenbank
PostgreSQL 16 (W4)
PgBouncer :5433
18 MVs
80+ Tabellen
pg_trgm
mv_quality_tiers
Infra & Tools
6× Contabo VPS
Nginx + Let's Encrypt
Docker
Telegram Bot v2
Redis
rclone
14
Live-Cluster-Status
7 Server (M+W1+W2+W3+W4+W5+W6) · Heartbeat · w4_auto_solver · cluster_full_scan · Echtzeit
Lade 7 Server...
ServerIPRAMRolleDaemonsAD-Worker
Master161.97.79.19216GBAPI + Orchestrator + Nginx15+5
Worker-1173.212.217.3716GBATS + Enrichment + Quality128
Worker-2161.97.170.20516GBCareer + Triple + BA-Fetcher108
Worker-395.111.233.047GBDescription Shards + Booster512
Worker-4 (DB)5.189.174.15248GBPostgreSQL Primary + PgBouncer00
Worker-5173.212.253.11516GBAdvertsdata dediziert + HR212
Swap: 28GB Swap-Cluster (alle 7 Server). Watchdog Cron 06:00 täglich. Worker reduziert bei hohem Swap.
15
Datenbank-Schema
80+ Tabellen · 18 MVs · PostgreSQL 16 auf W4 · PgBouncer :5433 (pool_size 80) · pg_trgm
TabelleRowsBeschreibungKategorie
job_advertisements1.41MVP-Stellenanzeigen mit Enrichment (76+ Spalten)Core
advertsdata_jobs1.09MAdvertsdata-Stellenanzeigen (Email 82%, Phone 87%)Core
placement_scores1.41MPlacement-Score pro Stelle (0-100, Grades S/A/B/C/D)Analytics
hr_companies260KFirmendatenbank mit HRB, Domain, GradeHR
hr_contacts162KHR-Kontakte mit Name, Email, Phone, Grade (KQI 80.8%)HR
crawler_sources272KAlle registrierten DatenquellenCore
gmaps_discoveries595KGoogle-Maps-Firmendatenbank (W6 dediziert)GMaps
hiring_signals19.6KHiring-Signale (5-Faktor Composite Score)Analytics
gvp_members8.6KGVP-Personalvermittler (5 Layer Enrichment)Outreach
company_momentum2.4KWoche-über-Woche Hiring-MomentumAnalytics
offeneregister_raw2.39MHandelsregister-Daten (JSONL Import)HR
+ 70 weitere TabellenUsers, Watchlist, Outreach, Notifications, MVs...Support

18 Materialized Views (Refresh alle 2-15 Min)

mv_dashboard_kpis (2min)
mv_trends_overview (5min)
mv_branchen_detail (15min)
mv_direkt_hero (15min)
mv_ats_breakdown (15min)
mv_special_sources (15min)
mv_fachkraeftemangel (15min)
mv_source_quality (15min)
mv_region_stats (15min)
mv_emptype_mix (15min)
mv_email_quality (15min)
mv_daily_trend (15min)
DB-Host:   W4 (5.189.174.152) — PostgreSQL Primary
Zugriff:   127.0.0.1:5433 (PgBouncer auf Master) — NIEMALS Port 5432!
Worker:    161.97.79.192:5433 (Master-PgBouncer)
Pool:      80 Verbindungen · Session-Mode
Backup:    W4 täglich 03:00
16
Crawler-Infrastruktur
150+ Python-Scripts · 43+ Daemons (partitioniert _p0-_p3, PID-Lock) · 64 Advertsdata-Worker · 13 GMaps Docker-Container · 24/7
43+ permanente Daemons
Laufen 24/7 auf 5 Servern: Master (15+) + W1 (12) + W2 (10) + W3 (5) + W5 (2). 6/6 Partition-Daemons mit PID-Lock. daemon_keeper */1 Cron.
📊
64 Advertsdata-Worker
Playwright-basiert auf 5 Servern (M8+W1-8+W2-12+W3-20+W5-16). 1.09M+ Stellen gescrapt.
🔄
Enrichment-Pipeline
5-stufig: Impressum → Domain → E-Mail → Phone → Quality-Score. Plus: HR-Matcher, Handelsregister-Enricher, Trigram-Matcher.
DaemonServerFunktion
backend (FastAPI)MasterAPI :8003, 200+ Endpoints, Background-Refresh, Warmup
orchestratorMasterKoordination, Heartbeat-Check, Worker-Monitoring
telegram_control_botMasterBot v2: 10 Commands, 39+ Aktionen
briefing_auto_analystMaster3-Stufen (Regel-Engine → Claude API → Telegram)
ats_crawlerW116 ATS-Systeme (Personio, Softgarden, Greenhouse...)
enrichment_pipelineW1Impressum + E-Mail/Phone-Enrichment 24/7
quality_scoreW1Quality-Scoring (5K Batch/60s)
shadow_monitorW1Master-Failover (20s Zyklus, auto-Promotion)
career_page + career_htmlW2Career-Page-Checks + HTML-Parsing
triple_enricherW2GMaps + Impressum + Phone kombiniert
ba_api_fetcherMasterBA REST-API (aiohttp, 15 concurrent, ~100/s, 65% OK)
description_daemonW3Sharded Description-Fetching (Shard 4+5)
advertsdata_scraperW520 dedizierte Playwright-Worker
vp_hr_matcherCronVP↔HR Trigram-Matching (Daemon, 4 Partitionen)
ad_vp_matcherCronAdvertsdata↔VP Trigram-Matching (GIN-optimiert)
17
API-Dokumentation
200+ Routen · FastAPI :8003 · 300s Response-Cache · Background-Refresh 120s

Öffentliche Endpunkte

GET /api/public/briefing — System-Briefing (kern.jobs_combined)
GET /api/public/signals — Hiring-Signale
GET /api/public/stats — Basis-Statistiken
GET /api/monitor/full — Monitor-Dashboard (15 Sektionen)
POST /api/v1/auth/login — JWT-Authentifizierung

Customer Portal (/api/v1/)

GET /dashboard/kern — Fast KPIs (<300ms)
GET /dashboard/overview — Full Dashboard
GET /jobs/placement — Placement Engine
GET /jobs/placement/by-job — Job→Firmen
GET /jobs/placement/by-company — Firma→Stellen
GET /stellenanzeigen/enriched — HR-enriched Jobs
GET /hr/contacts — HR-Kontaktdatenbank
GET /qualitaet/overview — Datenqualität
GET /qualitaet/dach-report — DACH-Markt-Report
GET /companies/momentum — Hiring-Momentum
GET /contacts/ — Contact Intelligence
GET /gvp/ — GVP-Analysen
GET /analytics/shortage — Engpass-Radar
+ 30 weitere Endpoints

Admin Portal (/admin/api/)

GET /admin/api/dashboard — Admin-KPIs
GET /admin/api/monitor/live — Live-Status
GET /admin/api/intelligence/* — Quality, Salary, Shortage
GET /admin/api/crawler/* — Crawler-Stats
GET /admin/api/hr-kontakte — HR-Dashboard
GET /admin/api/advertsdata — Advertsdata-KPIs
POST /admin/api/auto-analyst/trigger
+ 40 weitere Endpoints

Performance

Global Response Cache: 300s TTL auf alle GET /api/*
Background-Refresh: Alle 120s warm (Portal+Admin Token)
Startup-Warmup: 30+ Endpoints beim Boot
18 MVs: Keine Full Table Scans mehr (mv_quality_tiers neu)
Redis: Briefing + Monitor Cache (Cross-Worker)
Cached Response: <100ms (X-Cache: HIT)
18
Automatisierung & Cronjobs
47+ Cron-Einträge auf Master · 15 auf W1 · 10 auf W2 · 24/7
ZeitScriptFunktion
Monitoring (alle 2-30 Min)
*/2vakanzpuls_watchdog + MV-Refresh (KPIs)Daemon-Überwachung + Dashboard-MVs
*/5worker_scheduler + MV-Refresh (Trends)Phase-A/B + Trends-MV
*/15system_health_check + MV-Refresh (7 MVs)Health + Branchen/ATS/Region/Email MVs
Tägliche Pipeline-Kette (chronologisch)
02:30shortage_radarEngpass-Radar (241 Gruppen)
03:00hiring_signalsHiring-Signale (5-Faktor, 19.6K)
04:30advertsdata_hr_importAD→HR Import Pipeline
05:30Matcher DaemonVP↔HR Trigram (4 Partitionen)
05:45name_extractorGF-Namen aus raw_text (130K)
05:50gf_email_enricherGF-Email Pattern-Erkennung
05:55advertsdata_vp_matcherAD↔VP Trigram (GIN-optimiert)
06:15momentum_trackerWoche-über-Woche (2K Firmen)
06:30placement_scorer + wakeup_checkerScore 0-100 für 1.36M Jobs + Pipeline-Wakeup
07:00stier_digestNeue S-Tier Jobs → Telegram
07:30skill_extractor28 Skills, 200K Jobs/Batch
08:30morning_briefingTelegram-Statusbericht
Spider (06:00-09:00 auf W1+W2)
06:00-09:0012 Spider (Interamt, Stellenwerk, AWO, DRK...)25K+ öffentliche Stellen täglich
18b
Always-Working System
6 Daemons · Kein System darf idle sein · Auto-Analyst

Seit April 2026 sorgt das Always-Working System dafür, dass alle Crawling- und Enrichment-Prozesse permanent arbeiten. Kein Daemon bleibt unbemerkt idle — automatische Erkennung und Wiederherstellung in unter 60 Sekunden.

🤖
Briefing Auto-Analyst
Liest alle 30 Min den Briefing-Endpunkt, erkennt Probleme via Regel-Engine (12 Regeln) + Anthropic Claude API + AOE (Autonomous Optimization Engine). LOW-Risk auto-execute, MEDIUM Telegram-Buttons, HIGH Admin-Portal. Nachtmodus 23-07 Uhr.
👁
Never-Idle Monitor
Prüft alle 5 Min: GMaps-Queue leer → Auto-Neustart, Description-Rate unter Schwellwert → Alert, E-Mail-Pipeline stagniert → Alert + Restart, Worker-Heartbeat prüfen.
🐳
GMaps Docker Monitor
Läuft auf W1 und W2 lokal. Prüft alle 60s ob gmaps_turbo.py und alle 8 gosom-Container laufen. Erkennt Hung-Container (0% CPU >5 Min), startet automatisch neu.
📝
Description Booster
50 concurrent HTTP-Requests 24/7. Zielt auf Jobbörsen, ATS-Softgarden/Greenhouse/Lever/Personio/Ashby. Rate: ~278 Beschreibungen / 30 Sekunden = ~33.000/h.
🤖
BA-Description-Fetcher
Playwright-basiert (15 Tabs), speziell für Bundesagentur für Arbeit (JavaScript-rendered). Ziel: 743K BA-Jobs mit Beschreibung in ~34 Tagen.
📧
Domain Email Booster
40 concurrent. Domains mit meisten offenen Jobs zuerst. Alle bekannten Impressum-Pfade. E-Mail-Propagation auf alle Jobs einer Domain. Ziel: 247K Domains.

Briefing Auto-Analyst — Regel-Engine

BedingungAktion (LOW-Risk, sofort)Cooldown
apollo.daemon = falseApollo-Daemon starten6h
emails_pro_stunde = 0Enrichment-Pipeline prüfen + Restart2h
GMaps Queue pending=0 + idlegmaps_jobs auf 'pending' zurücksetzen → Zyklus startet1h
BA-Fetcher nicht aktivBA-Fetcher starten4h
desc_pct < 25% + Booster downDescription-Booster neu starten4h
E-Mail-Rate < 60%Email-Booster-Status prüfen6h
GMaps-Karriere-Funnel < 100/24hUngecheckte Karriereseiten analysieren24h
GVP ohne E-Mail > 50%GVP-Kategorien analysieren24h
Alle Daemons aktiv aber Output=0Prozess-Status-Snapshot3h
Claude API Integration: Wenn ANTHROPIC_API_KEY gesetzt, analysiert Claude Sonnet nach jedem Regel-Engine-Durchlauf das aktuelle Briefing und identifiziert 2-3 weitere Optimierungen — diese werden als Maßnahmenplan per Telegram gesendet.
Teil DBetrieb & Wartung
19
Monitoring & Alerting
Telegram · UptimeRobot · Morning-Briefing
📱
Telegram-Alerting
Alle kritischen Events sofort per Telegram-Bot: Daemon-Crashes, Worker-Ausfall, Backend-Down, hoher Load, Spider-Stale.
🤖
UptimeRobot
Externer Monitor prüft Backend-API alle 5 Minuten (HEAD+GET /api/health). Alert bei HTTP ≠ 200.
📋
Morning-Briefing
Täglich 08:30 Telegram: Jobs, E-Mail-Rate, Quality Score, Cluster-Health, GMaps-Status, Emails/h.
20
Failover & Redundanz
Shadow-Monitor · Hot-Standby · Auto-Recovery

JN — Heartbeat-System

Alle Server schreiben alle 30s in worker_heartbeats: Load, RAM, Daemons, Docker-Count, Queue. Orchestrator prüft alle 60s.

JO — Adaptive LB

adaptive_lb.py routet Tasks zum besten Worker. GMaps-Docker-Load herausgerechnet. RAM + Slots entscheiden.

JP — Master-Failover

shadow_monitor.py auf W1: bei 2× Ausfall (~40s) → W1 startet Backend :8004 + Celery-Beat. Auto-Recovery.

Im Failover verfügbar: Admin/Partner-Dashboard (W1:8004), Celery-Cronjobs, Telegram-Alerts, GMaps-Crawling. Nicht verfügbar: DB-Schreibzugriffe (DB liegt lokal auf Master).
21
Deployment
Git-basiert · nohup · add_worker.sh
# Deployment-Workflow:
git add -A && git commit -m "feat(KN): ..." && git push origin master

# Frontend rebuild (immer mit rm -rf .next!):
cd /home/zerocool/crawler/admin
rm -rf .next && npm run build
fuser -k 3003/tcp; sleep 8; nohup npx next start -p 3003 &

# Backend restart:
bash scripts/backend_restart.sh

Kritische Regeln

  • Immer rm -rf .next vor Build
  • DB-Host Worker: 161.97.79.192 (NICHT 127.0.0.1)
  • PgBouncer Port: 5433 (NICHT 5432)
  • Git-Branch: master
  • Backend NUR über scripts/backend_restart.sh

Daemon-Verteilung (42)

  • Master (13): orchestrator, reaktor, harvester, celery, heartbeat, bot, never-idle, auto-analyst, tis, aoe-executor, doku-updater, docker-monitor, apollo
  • Worker-1 (12): ats-crawler, mass-crawler, salary, phone, description, enrichment, quality, desc-booster, shadow, emptype, heartbeat, gmaps-daemon
  • Worker-2 (12): career-page, career-html, triple-enricher, ba-fetcher, description, desc-booster, domain-resolver, data-propagator, contact-completer, career-miner, heartbeat, gmaps-daemon
  • Worker-3 (7): description(shard4+5), desc-booster, career-page, triple-enricher, career-html, heartbeat, gmaps-daemon

+ 2 hiberniert: ats-email-enricher, domain-email-booster (reaktiviert bei >500 neuen GMaps-Domains/Tag)

Teil ERoadmap & Ausblick
22
Roadmap
Prompt-Chronologie A–LR-23 · Nächste Schritte

Abgeschlossene Meilensteine

Plattform-Grundstruktur (A–GF)
FastAPI-Backend, Next.js-Admin, PostgreSQL, erste ATS-Crawler, PgBouncer
Enrichment-Pipeline v2 (GG–HF)
Impressum-Crawler, E-Mail-Enrichment, Phone-Propagierung, Career-Page-Intelligence, GMaps-Discovery
Migration Master→Worker (IR–IS)
Master-Load 10.8 → 4.4. 5 schwere Daemons migriert. PG parallel_workers=0.
IQ-Features (JI)
Akuter Bedarf, Kundensegmentierung, Watchlist, Schnelltest, DACH-Report
GMaps-Zyklus v3 (JH)
12.271 neue Queries, Sofort-Neuzyklus, 13 Docker-Container parallel
Quality Score v3 + Dashboard (JJ–JK)
Kategorisierte Formel, E-Mail-Fix, Government-Description-Fetcher, Dashboard-Frontend
Master-Load-Optimierung (JL–JM)
Load 11.3→5.07. Celery=2, PgBouncer Pool=15, Backend workers=2, add_worker.sh, Phone-SKIP-LOCKED
VakanzRaid Cluster-System (JN–JP)
Heartbeat, Adaptive LB, Master-Failover/Shadow-Monitor. Cluster-Dashboard live.
JQ–JR — BA-Fetcher + Email-Booster + Telegram Bot v2
BA-Description-Fetcher (Playwright, 15 Tabs, 743K Ziel), Domain-Email-Booster (247K Domains), Telegram Control Bot v2 (10 Commands, 39+ Aktionen), GMaps Docker Monitor (W1+W2), Data Consistency alle 4 Portale.
JS–JT — Always-Working + Briefing Auto-Analyst
Never-Idle Monitor, Description-Booster (278 Desc/30s), briefing_auto_analyst.py (Regel-Engine + Claude API + Telegram-Approval), Employment-Type-Extraktion, Auto-Analyst im Admin-Portal.
JU–JY — Enrichment + Master-Entlastung
Claude API aktiv, GMaps-Career-Funnel, Phone +26.5K, ATS-Email-Enricher, Domain-Resolver, Data Propagator. 5 Daemons Master→W2 migriert (Load 14→9.6).
JZ–KE — TIS + Admin-Portal 7 Tabs
Telegram Intelligence System (Scanner, Classifier v3, Pranger, 516 Nachrichten), 7 Admin-Tabs (Auto-Analyst, Propagator, Doku-Updater, TIS), Umlaute-Fix, Telegram Spam-Unterdrückung.
KF–KK — AOE (Autonomous Optimization Engine)
Strukturierte Claude-Aktionen, Risk-Gate Executor, Telegram Inline-Buttons, Infra-Snapshot (129 Konstanten), Whitelist-Validator, Nachtmodus (23-07), Emergency-Stopp, Morgen-Briefing.
KL–KY — Pipeline-Fixes + Career Email Miner
desc_booster→W1, BA-Fetcher→W2, 16 Crons gefixt, AOE Anti-Eskalation, 4-Shard Description, Triple Enricher 6x, AOE Kalibrierung, Career Email Miner.
KZ–LA — Tagesbilanz + Briefing-Fix
Tagesbilanz 22:00 Telegram, Pipeline-Hibernation (Wakeup-Checker 06:30), Briefing 34 Daemons, Token-Auth, Backend run_in_executor.
LB–LF — 5 ATS-Spider neu aktiviert
Softgarden (18.808 Jobs, API→HTML), BambooHR (4K+ Jobs, embed2→careers/list), Breezy (5.376), Pinpoint (7.409), iCIMS (7.649). +44K Jobs.
LG–LH — Employment-Type + Ashby
EmpType 36.2%→41.7% (Normalisierung + Titel + Desc-Batch), Ashby 4.272 Jobs, Heartbeat in Watchdog.
LI–LL — Worker-3 vollständig integriert
95.111.233.0 (47GB RAM), 7 Daemons, GMaps 8+8+8→6+6+6→8+8+8 (24 Container), LoadGuard Docker-aware, Echtzeit-Dashboard.
LM–LN — 7 weitere ATS + W3 Auslastung
SmartRecruiters, Haufe, dvinci, Teamtailor, Workable, Join, Recruitee aktiviert. W3 +2 Daemons (triple+career_html).
LO–LP — AOE Redesign
Emergency-Stop-Bug gefixt (Cooldown≠Fehler), Nachtmodus 23-07 monitor-only, Auto-Approve Rate-Limit 3/h, Success-Tracking, 6 Telegram-Commands.
LQ–LS — Datenqualität-Merge + Health-Monitoring
MONITORING→DATENQUALITÄT Merge, LoadGuard per-Worker (load_5m), Proaktives Health-Monitoring (15min, 7 Checks), Doku-Updater Fix.
LT–LZ — Telegram Anti-Spam Overhaul
Zentrale telegram_utils.py (2-Stufen Rate-Limiter L1+L2, Digest-System), 15+ Direktaufrufe migriert, NOTIFICATION_CONFIG (25 Categories), DB-Rate-Limiter, Career Funnel Daemon.
MA–ME — Monitor Dashboard v1→v4
Bloomberg-Stil Monitor (6-Col Grid, Dot-Matrix Daemons, Server-Strips), /api/monitor/full (15 Sektionen, Redis 10s), server_metrics Tabelle+Collector (4 Server, Cron */2), SSL.
MF–MH — GMaps Stabilisierung + W3
GMaps Crash-Loop Fix, AOE Stabilisierung (aoe_blacklist, Loop-Detektion), W3 Integration komplett (Scheduler aktiviert, 8 Docker, 7 Daemons).
MI–MR — Pipeline Push + Cron-Audit
Enrichment Pipeline Tuning, Apollo Deep-Dive, Seismograph Qualität, Description Pipeline (~28K/h), Shortage Radar repariert, BA-Fetcher W1+W2 parallel, Employment Type Push (28K), 74 Crons inventarisiert, GVP Enricher L2.
MS — Monitor v5.0 + Performance
+Enrichment Pipeline & Signals Sektionen. Performance 60s→75ms (MV erweitert, Thread-Pool, Port 5432 direkt). Admin Server-Block auf server_metrics umgestellt. Hibernated Daemons analysiert (bleiben).
MT — Admin Bug-Fix Sprint (10 Bugs)
GVP-Farbe, XLSX-Export, Shortage-Radar (MAX computed_at), Branchen-/Bundesland-Filter ("Weitere"/"Unbekannt" raus), Live-Feed Zeitlogik, Quellen-Beschriftung, Behörden source_type LIMIT fix.
MU — /akuter-bedarf Deep Fix
Firmen-Links intern (→Schnellsuche), Stadt 63%→94% (COALESCE city+location), Email 20%→40%, 300s Cache.
MV — Schnellsuche Deep Search
Schnelltest→Schnellsuche umbenannt, Deep Search über 1.2M+ Jobs (248ms), Firmen-Detailseite mit paginierten Jobs (80ms), 2 Modi (Suche+Detail), Redirect /schnelltest.
MW — E-Mail-Qualität
is_valid_email() + email_score() SQL-Funktionen, 5.605 Fake-Emails bereinigt, DB-Trigger trg_clean_email, Email-Rate 40→46% (sauber, HR priorisiert).
MX–MY — Telegram Entrümpelung
critical_alert nur bei Criticals, status_report+Worker-Status+Night-Window deaktiviert, error_key-Fix in L2, Spider-Digest-Collector (10 Spiders, DB-Buffer, Cron 10:00). Telegram 42→~8/8h (−80%).
MZ — Kundensegmentierung + Branchen
Kundensegmentierung als Tab in /akquise (3 Tabs), Nav bereinigt, Branchen-Mapping erweitert (+3 Kategorien), XLSX-Export pro Zeile, "Weitere Branchen"→"Dienstleistung & Sonstige".
MZ+ — 3 neue ATS-Spider + Fixes
Concludis (71 Quellen), JazzHR (14), Taleo (8/113 Jobs) — Playwright-basiert. SuccessFactors bereinigt (45 SAP-Infra deaktiviert). ATS-Daemon W1 repariert (loguru + DB-Host 127→161). ATS Output-Check in critical_alert.
NX-1–9 — Customer Portal komplett (15/15 Pages)
Design System (globals.css, CSS Custom Properties), Dashboard, Stellensuche, Markt-Radar, Markt-Radio, Engpass-Radar, Watchlist, Info-Agenten, Markt-Analyse (Recharts), Export, Settings, Company Detail, Innovationen, Companies List, Job Detail.
NX-10 — Backend Foundation
Watchlist API (CRUD+Sync), Activity Tracking (user_activity_log), Password-Change Endpoint, localStorage→API Migration. 2 neue DB-Tabellen.
NX-11 — Hiring Momentum Detector
company_momentum Tabelle (2.000 Firmen), momentum_tracker.py (Cron 06:15), /momentum Page (Grid+List), Company Detail Momentum Badge. Innovation #7.
NX-12 — Placement Probability Engine
placement_scores (~1.27M Jobs), 10-Faktor Score 0–100, Grades S/A/B/C/D, placement_scorer.py (Cron 06:30), /placement Page (ScoreRing, FactorBadges). Innovation #6.
NX-13 — Mega-5 Features
Contact Intelligence (/contacts), Quellen-Health (/sources-health), Score Evolution (placement_score_history), S-Tier Digest (Telegram 07:00), Skill-Tag Engine (job_skills, 28 Skills, skill_extractor.py Cron 07:30).
NX-14 — Mega-4 Features
GVP-Analysen (/gvp, 8.567 Members), Saved Searches API (CRUD), Skill-Market-Map (/skill-map, Heatmap Skill×Stadt), Dashboard Upgrade (Grade-Distribution, Top Skills).
NX-15 — Company Profile 2.0 + DACH-Report
Company Detail: Skills-Tab (Skill-Cloud), Evolution-Tab (SVG Sparkline). DACH-Report Generator (/dach-report, PDF Print). Widget API (job-count, skill-trend, API-Key Auth).
NX-16 — User Management + Outreach-Center
User-Management (/admin/users, Owner-only CRUD). Outreach-Center (/outreach, Kampagnen+Templates+Opt-Out). OUTREACH_ENABLED=false — wartet auf Domain. Nav: AKQUISE+ADMIN Sektionen.
NX-17 — Quality Sprint
Placement API Fix (Router-Reihenfolge, 4.446 S-Tier jetzt erreichbar). Docker False-Positive bereinigt (96% waren Logistik-Container). Skill Dictionary 28→50 Skills. Extractor Batch 50K→200K.
NX-18 — Streaming Skill-Extractor + Score Evolution
Skill-Extractor: 2GB→2MB RAM (Streaming Chunks, sofortige Commits). Score Evolution API mit Trend-Analyse (per_day, forecast_7d, volatility, stier_delta).
NX-19-A — Outreach CP-Ready
Template-Editor mit Live-Preview + Variablen-Sidebar + Checkliste. GVP v2 HTML-Template (professionell, Stats-Widgets). CP-Checkliste auf /outreach. Setup-Guide (/outreach/setup, 5 Schritte bis Go-Live). 3.214 Kontakte importiert.
NX-19-B — Score Evolution Dashboard
/evolution Page: Top-Mover Ranking (Aufsteiger+Absteiger), Zeitraum-Filter, Firmen-Suche mit Trend-Analyse, CSV-Export (5.000 Firmen). Trend-Badges (▴/▾) auf Momentum-Karten. Dashboard-Widget Top-Aufsteiger 7d.
NX-19-C — Notifications-Center
Bell-Icon mit Unread-Badge im Header (alle Pages). /notifications Vollseite mit Type-Filter. portal_notifications DB (per-user read-tracking). S-Tier Digest schreibt automatisch Notifications. Internal API für Daemons.
NX-19-D — Mobile + Polish
Responsive CSS-Grid-System (vp-grid-4/2col/2eq/6). Mobile Breakpoints 767px+1023px. Page-FadeIn Animation, Button Active-Scale, Focus-Visible A11y. ErrorBoundary + EmptyState Komponenten. Dashboard/Outreach/Evolution/Momentum responsive.
NX-20 — Dashboard UX Redesign
Welcome-Flow: 3-Ziel Onboarding-Modal (Vermittlung/Analyse/Outreach) beim Erstlogin. Dashboard ActionCard personalisiert nach Ziel. PageIntro Kontexthilfe auf Intelligence-Seiten. FeatureHint Discovery-System auf Dashboard. Onboarding-State in users DB + /me API.
NX-21 — Completion Sprint
PageIntro auf 10/10 Intelligence-Seiten. /demo (öffentlich, Live-KPIs, Feature-Showcase). /dashboard-print (A4 PDF-optimiert). /admin/analytics (DAU, Onboarding-Goals, Feature-Adoption, Top-Pages). 34 Portal-Pages total.
NX-21 Hotfix — UI Polish
Sidebar 260px, Bell z-index 9999, 3 KPIs, Header User-Pill, Performance-Cache (Search 8s→40ms).
NX-22 — Dashboard Performance
/kern Fast-Endpoint (845ms→17ms cached). 2-Stufen-Laden: KPIs sofort, Rest im Hintergrund. gvp_members Fix. 120s Cache.
NX-23 — W4+W5 Cluster + Monitor v6.0
W4 (48GB): PostgreSQL Primary via Streaming Replication, Zero-Downtime Switchover. W5 (48GB): Dedizierter Advertsdata-Scraper (20 Playwright Worker). Monitor v6.0: 6 Server, Advertsdata Cluster Echtzeit (390 Stellen/min), GMaps/AOE/HotList ersetzt. 57 Worker auf 5 Servern, 429M ID-Range (2041M–2470M).
NX-24–39 — Portal + HR-Pipeline
/stellenanzeigen+/hr-kontakte Portal, PDF-Vorschau, DACH-Filter, VP-Matcher v3+v4, Sammel-Email-Filter, Duplikat-Fix, Employment-Type in Kacheln, Namen-Extraktor (6.053 mit Namen), Phone-Matching.
NX-40–43 — Landing Redesign
Blue-System (#1D4ED8), Plus Jakarta Sans, Logo-SVG, Lucide Icons (keine Emojis), Mega-Menu, 8 Feature Sub-Pages mit Portal-Mockups, MockupBrowser-Komponente, Stats-Bar. 15 Landing-Pages.
NX-44–49 — Portal Dark Sidebar + Light Theme
Dark Sidebar #111827 collapsible, Blue-System Portal, Login Slideshow, Umlaut-Fix, HR-Kontakte+Stellenanzeigen Light Theme, Sidebar User-Block entfernt, Blue Stripe+Pill-Highlight, Dashboard Badges. advertsdata 49→64 Worker.
NX-50 — HR-Kontakte 2.0 + Firmenprofil
HR-Kontakte erweitert: HRB-Badge, Position-Filter (GF/Vorstand/Inhaber), HR-verifiziert Toggle, CSV/Excel Export (10K Kontakte). Neue Firmenprofil-Page /hr-kontakte/firma/[id]: Dark Hero mit KPIs, Ansprechpartner-Liste (HR-verifiziert Badge), aktive Jobs mit Placement Score, Firmendetails Grid (HRB, Registergericht, Branche). 37 Portal-Pages.
NB — System-Hygiene Sprint
/tmp Scripts bereinigt (alte DB), GMaps Duplikate W1+W2 gekillt (W3 Load 52→7), critical_alert nur bei Criticals, Briefing direkt_total+hot_list live aus MV, Wachstumsseite dynamisch, /system UNKNOWN-Fix, AOE Blacklist-Emergency-Fix.
NC — DB-Crash Prevention + Briefing
Legacy 536K Emails→api_direct, desc_milestone_checker (Cron */2h), DB-Crash Fix (MV CONCURRENTLY+UNIQUE INDEX), Briefing 139s→47ms (Port 5432), Health-Check 3 Retries.
NF — Handelsregister-Enricher
Playwright-Scraping handelsregister.de (offizielles Registerportal). SI-XML Download (xJustiz-Format) für GF-Namen-Extraktion. HRB+Registergericht in hr_companies, 81% Trefferquote, ~9s/Firma. 27.300 registerpflichtige DE-Firmen. Ziel: Coverage 34%→60-75%.
NX-51 — Monitor v6.3 + W2-Fix
Monitor HR-Kontakte erweitert (Mit Name %, HRB-Count, OR/HR-Quellen). offeneregister-Block im Monitor (2.4M Firmen, 1.9M Officers, 21K Matches). VP-Matcher ETA-Fix (“Daemon Sleep” statt “Wartend”). W2 advertsdata 12→8 Worker (87%→40% RAM). offeneregister SQLite-Matcher+JSONL-Import abgeschlossen: 21.778 Matches, 56.209 GF-Namen, 21.762 HRB.
NX-52 — Description-Fix + Tagesplanung
Description-Pct Fix in admin_api.py (fehlender LENGTH>50 Filter — 99.5%→47.4%). Neue Akquise-Tagesplanung (/akquise/tagesplanung): Score-basierte Priorisierung (Grade+Verifizierung+Email+Phone), Quick-Actions (Kontaktiert/Interessiert/Notiz/Skip), Pipeline-Stats, Progress-Ring, Notiz-Modal. Nav-Eintrag unter AKQUISE. 39 Portal-Pages.
NG — Handelsregister-Enricher v2
Umlaut/Sonderzeichen-Fix im Name-Matching (ae/oe/ue/ss). --only-not-found Flag für v2-Retry. GF-Email-Enricher: Pattern-Erkennung aus existierenden Emails + company_domain Lookup aus job_advertisements. 48 GF-Emails generiert (email_type=‘generiert’). Cron 05:50 täglich.
NX-71 + NG — Monitor Smart-ETA + Adaptive Matcher-Architektur 12.04.
Monitor rMatcher(): 3-Modi ETA — „Echtzeit-Modus ✓“ (pct≥99.5% + pending<500), „Bulk-Cron in ~Xh“ (pending<5K, nächster Cron 02/06/12/18), Rate-basiert sonst. Adaptive Matcher: pg_notify-Trigger `new_ad_job` auf job_advertisements(INSERT WHERE hr_enriched_at IS NULL), `--adaptive` Flag mit LISTEN/NOTIFY via select.select(), adaptive Sleep 5-60s und Batch 20K-200K je nach Backlog. advertsdata_vp_matcher_bulk `--max-hours`-Arg, Bulk-Cron 1× 02:00 → 4× (02/06/12/18) je 1.5h (64 Crons aktiv). Briefing matcher-Block erweitert: pending, no_match_sentinel, matched_last_hour, matched_today, mode (steady_state/catching_up). Live-Verify: mode=steady_state, pending=160, matched_today=41.164.
NH — offeneregister Bulk Import
5.3M deutsche Firmen aus offeneregister.de: JSONL (260MB, 2019) + handelsregister.db SQLite (3.7GB, 2.2M Firmen, 2022). Streaming-Import (bz2 zeilenweise, 5K Batch). SQLite Direct Matcher (FTS5+Jaccard, 16.6% Match-Rate). 5M Positions (3.8M GF) + 2.4M HRB-Nummern. Erwarteter Uplift: ~13K neue Matches, ~25K GF-Namen, Coverage 37%→70%+.
NI — handelsregister.ai API
Tagesaktuelle GF-Daten via REST-API für post-2022 Firmen + schwierige Namens-Matches. 500 Credits (7/Request), 60 Firmen verarbeitet: 36 HRB + 24 GF-Namen. CSV-Enricher-Batches (100er) für manuellen Upload vorbereitet. 201 Credits verbleibend.
NJ — Apify Handelsregister Scraper
Apify Actor (dominic-quaiser/handelsregister-scraper): Input-Schema reverse-engineered (firma_schlagwoerter statt searchQuery), vorname/nachname Parser, phonetische Suche. ~30s pro Firma, $5 Free Trial. Briefing um apify-Quelle erweitert (5. Enrichment-Quelle).
NK — Server-Stabilisierung + Monitor v6.2
Swap auf allen 6 Servern (28 GB gesamt, persistent via fstab). Worker reduziert: W3 20→12, Master 8→5, W5 19→12 (RAM 98%→7-28%). Monitor v6.2: Swap-Balken, Available-RAM Anzeige, Daemon-Offline-Namen im Badge, RAM-kritisch Border. server_metrics erweitert (+swap_total/used, ram_available, advertsdata_workers). Swap-Watchdog Cron 06:00 mit Telegram-Alert bei RAM>95%.
NL — Description-Vollständigkeits-Audit
Audit: advertsdata_jobs hat KEINE description-Spalte (nur raw_text = Metadaten). 600K BA-Jobs waren als ‘[nicht extrahierbar]’ markiert — BA-Fetcher Query-Fix um diese erneut zu versuchen. Monitor description_pct Fix (eigene Berechnung totDesc/tot inkl. advertsdata = 30% → direkt aus MV = 47.4%). BA-Fetcher auf W1 gestartet (Playwright EPIPE-Problem bei BA-SPA-Seiten).
NM — Description-Fetcher + Diagnose
workday_desc_fetcher.py (GraphQL) + jobboerse_desc_fetcher.py (HTTP) erstellt. Ergebnis: Workday-Jobs abgelaufen (404), Adzuna blockiert Bots (403). ALTER TABLE für description_source blocked durch Long-Transactions. 47.4% ist realistischer Ist-Stand — Steigerung nur über BA-Playwright möglich (~600K Jobs, ~2 Wochen Laufzeit).
NN — Domain-Propagation + Dropcontact
Domain-Propagation: hr_companies.domain befüllt aus company_domain (9.032) + Email-Domain (1.347) = 10.379 Firmen mit Domain (vorher 0). Dropcontact Email-Enricher: API-Integration mit Polling-Fix, 50 Credits verbraucht, 60% Trefferquote bei Top-Kontakten (~11 verifizierte GF-Emails). Briefing erweitert um firmen_mit_domain. 9.800 Kontakte bereit für weitere Dropcontact-Batches.
NO — advertsdata↔VP Trigram-Matcher
GIN-optimierter Trigram-Matcher v3 (% Operator, 0.45s/Job statt 10s Seq Scan). Score: position*0.50 + company*0.35 + location*0.15, Threshold ≥0.65. Nur DACH-Jobs. 5 neue Indizes, 4 neue Spalten. Match-Rate ~5% (Stichprobe 10/200), geschätzt ~17K Matches. Email/Phone-Propagation in leere VP-Felder. Cron 05:55 täglich.
NX-53 — Datenqualitäts-Dashboard + DACH-Report
Neues /daten-qualitaet Dashboard: Gesamt-Score Ring (gewichtet), 3 Sektionen (Jobs/HR/Firmen) mit Fortschrittsbalken, E-Mail Validierung (Format/Privat/Generisch), Offene Backlogs, Qualität nach Quelle (Tabelle mit Ampeln). DACH-Report Upgrade: 4 Tabs (Regional/Branchen/Top-Arbeitgeber/Hiring-Trend), KPI-Zeile, 30d Sparkline, Employment-Type Mix. Backend: /api/v1/qualitaet/* mit 300s Cache. 40 Portal-Pages.
NP — Backend-Fixes
Briefing: kern.jobs_combined (VP 1.36M + Advertsdata 826K = 2.19M gesamt). Watchdog: HIBERNATED-Liste auf 14 Daemons erweitert (GMaps gestoppt, Legacy-Namen, ATS-Email/Domain hiberniert). Matcher: Load-Throttling (>8.0 Load = 30s Pause, >5.0 = 2s).
NX-54 — Zahlen-Konsistenz + Performance
Jobs-Combined 2.19M in allen Portalen. Performance 300x (12 MVs). SWR-Cache. Token-Expiry-Erkennung.
NX-55 — Placement Dual-Mode + Port-Fix
3 Tabs (Alle/Job→Firmen/Firma→Stellen). 5 Scripts Port 5432→5433 gefixt. Scorer 1.36M Jobs auf Produktion.
NX-56 — Monitor Rate-Fix + BA-Fetcher
AD Rate 106/min live. ETA robust. BA-Fetcher aus HIBERNATED + MASTER_DAEMONS aufgenommen.
NQ — Pipeline-Serialisierung
Crons gespreizt (Scorer 07:00, Momentum 07:15). Matcher Watchdog. 53 Worker, 390/min Peak.
NR — Pipeline nice-Priorität
10 Crons nice -n 15, Matcher nice -n 10. AD-Worker CPU-Vorrang.
NS — AD-VP Company-First Matcher
21.290 exakte Firmen-Matches. Cron 02:00 nachts.
NT — Monitor ETA-Fix
ETA robust: negative Werte, Fertig-Check, Rate-Info.
NU — GVP Self-Enricher
Email 66%→98.1% (+2.749), Website 63%→87.6% (+2.144). 5 Stufen.
NV — GVP Live-Stats
Briefing + Monitor: email_pct, website_pct, Quellen-Breakdown.
NW — GVP GF-Enricher
GF 64%→81%+ aus offeneregister (1.59M GF). Cron monatlich.
NX-57 — Innovationen + Doku-Fix
Roadmap aktualisiert. Doku zeigt jobs_combined.
NX-58 — Performance /contacts + /skills
/contacts 33s→0.43s (conditional JOIN), /skills/top 11.4s→0.24s. Stats aus MV. Cache 300s.
NX-Stabil — Systemstabilisierung
Backend MALLOC_ARENA_MAX=2. Restart 03:55. TIS resolved_at (735 auto). AOE Blacklist 14→8.
NY — AD→VP Email-Propagierung Fix
+1.698 Emails sofort (58.04%→58.16%). Script permanent gefixt.
NX-59 — GVP-Analysen Upgrade
KPIs: GF-Name 82.6%, Email 98.1%, Website 87.6%, Telefon 97.6%. Vollständig (alle 4): 6.125 (71.5%). Prozent-Farbkodierung. Email-Klick-Kopieren.
NX-60 bis NX-64 — Admin Redesign + Light Theme + Landing Live-Zahlen (11.–12.04.)
Admin Portal Redesign (Sandro-Rolle, system.tsx Split, GVP XLSX, PartnerNav), PartnerNav reduziert + withLayout HOC, PartnerUI Light + Dashboard Split 466→48Z, Landing Hero 2.28M/+110K aus Briefing, Light Theme fuer alle 15 Partner-Seiten via globalem CSS-Override.
NZ + HOTFIX-1–5 — Cluster-Stabilisierung 11.04.
Daemon-Fixes (desc/W1/W5/auto_healer), Master-Cron Recovery 2→49 mit zentralem Cron-Deployer (crons/*.crontab + deploy_crons.sh), Load-Throttler + Disk-Monitor auf allen 6 Servern, SmartRecruiters Dev2 (4.728 NULL company_name deaktiviert), False-TG-Alerts (critical_alert + never_idle + gmaps_watchdog) unterdrueckt.
NX-65 (Infra) — Script-Sync + Alert-Ruhe 12.04.
deploy_scripts.sh (rsync+setsid) verhindert stale heartbeat_sender auf Workern, HEARTBEAT in worker_watchdog (self-healing), WORKER_TIMEOUT 90→300s + OFFLINE_CONFIRM=3 (keine Deploy-Alert-Spikes), Backend heartbeat-Fenster 90→300s, W5 advertsdata 20→12 Worker (RAM 98→7%).
NA — Metric Registry + Dashboard-Bug 12.04.
Customer Dashboard zeigte 2.58M (pg_class.reltuples inkl. inaktive Rows) → Fix auf mv_dashboard_kpis.jobs_active + COUNT advertsdata_jobs = 2.28M. metrics.ts (12 METRIC_DEFS) + useBriefing Hook im Customer Portal. Erklaerende Labels "DACH-Stellen (gefiltert)" / "VP-Direktquellen, aktiv" / "Aktive Stellen (Gesamtmarkt)" auf Dashboard/Stellenanzeigen/Schnellsuche/PartnerDashboard.
Umlaut-Audit 12.04. — 25+ Dateien / 72 Zeilen
HTML-Entities &auml; / Unicode-Escapes \u00e4 / ae-oe-ue alle korrekt auf ä/ö/ü in Admin + Customer Portal. URL-Paths + DB-Felder + Funktionsnamen bewusst unveraendert (Python-Skript /tmp/umlaut_fix.py als Template).
NB — Quality Snapshot + Milestone-Tracker 12.04.
quality_snapshots + quality_milestones DB-Tabellen, scripts/quality_snapshot.py (Cron 23:50 via zentralem Cron-Deployer), Telegram-Milestones via telegram_utils. Neue API /api/v1/quality/history + /api/v1/quality/checks (5 Checks: desc/email/phone/kategorie/employment_type mit Ampel + ETA). Erste Werte: desc 48.5% / email 58.36% / phone 36.11% / backlog 705K.
NX-65 (Frontend) — Quality-Dashboard 12.04.
Monitor v6.4 DescPct-Widget (Progress-Bar + Wochen-Delta + ETA). Customer /daten-qualitaet: Live-Checks-Block mit 5 Ampel-Items + Zeitverlauf LineChart (Recharts) mit 85%-Ziel-Referenzlinie in Gold #C9A84C + 7/30/60T-Toggle + ETA-Card.
NX-66 — Monitor Overlay-Fix 12.04.
Im Monitor-Dashboard W1-Zeile zeigte dauerhaft "enrichment offline" (ragte in Nachbar-Spalte). Ursache: Daemon-Namen "enrichment" + "emptype_extractor" waren noch in DG['W1'] hart kodiert, aber die Daemons wurden retired (heartbeat_sender.py schon bereinigt). Fix: beide aus monitor/index.html Zeile 470 entfernt. W1 zeigt jetzt korrekt 7 Daemons ohne Ghost-Offline-Badges.
NX-66b — Daemon-Tooltip Z-Index-Fix 12.04.
Daemon-Hover-Tooltips wurden vom Advertsdata-Panel verdeckt. Ursache: .ddt war position:absolute im .dd-Parent, z-index:9999 galt nur im Panel-Stacking-Context. Fix: Umbau auf einen einzigen body-level #ddtip (position:fixed, z-index:99999, pointer-events:none) mit data-tip-Attribut an jedem Dot und globalem mouseover-Delegator. Viewport-Edge-Check (rechts/oben) eingebaut.
NX-67 — API Credit Check + /docs/wachstum ROI 12.04.
scripts/check_api_credits.py (Apollo/Hunter/Dropcontact/Serper/SendGrid/handelsregister.ai) ausgefuehrt — Apollo+Hunter+SendGrid aktiv, Dropcontact 403 (Header-Variante pruefen fuer NX-68), Serper Key fehlt. ROI-Tabelle 9 Services + Budget-Footer (Sofort 78€/Mo, +Hunter 99€/Mo, Bundesanzeiger 0€) direkt in docs/vakanzpuls_wachstum_v2.html eingebaut (Nginx routet /docs/* auf Backend :8003, nicht Next.js — verifizierte Live-URL). backend/app/services/dropcontact_service.py als Integration-Stub (Full in NX-68). Memory-Regel verify_every_task um Routing-Check erweitert.
NX-68 — Dropcontact + Apollo + SendGrid + Monitor v6.5 12.04.
Dropcontact Auth geloest: POST /batch mit X-Access-Token (nicht /v1/enrich wie in Doku). bulk_enrich_from_hr_kontakte() auf public.hr_contacts + hr_companies (nicht hr_kontakte-Schema), Spalten enriched_via/enriched_at migriert. 5-Kontakte-Testrun OK (0/5 Treffer bei StepStone-URLs + Trial; 13 Credits verbleibend). Apollo Free-Plan bestaetigt via 403 API_INACCESSIBLE → Upgrade Basic €49/Mo noetig. SendGrid 100/Tag Free-Alert im Admin Dashboard (Echtzeit-Cockpit Banner mit Upgrade-Links). Neuer Endpoint /api/v1/quality/api-status liefert 6 APIs mit Status. Monitor v6.5 mit Paid-APIs-Panel (Prio-Alert, 5min Client-Cache).
NC-TMG + NX-69 — §5 TMG Impressum Email Extractor + Monitor v6.6 12.04.
scripts/tmg_email_extractor.py — BeautifulSoup-Scraper mit 15 Impressum-Pfaden + mailto/Regex + Jobboersen-Blacklist (StepStone/Indeed/Personio/Greenhouse/etc), nice 15 Daemon ueber setsid/nohup. Schema hr_companies erweitert: email + email_source + email_alternatives TEXT[] + tmg_checked_at, Partial-Index fuer Backlog-Queue. Gefundene Emails werden gleichzeitig als hr_contacts-Zeile (source=§5_tmg_impressum, email_type=generic) angelegt. Briefing /api/public/briefing um tmg_extractor-Block erweitert (separate psycopg2-Connection wegen Transaction-Isolation). Monitor v6.6 mit §5-TMG-Panel (Found/Checked/Backlog/Hit-Rate). NX-69: /docs/wachstum — Bundesanzeiger §5 Status „offen” → „aktiv ✓”. Dry-Run: 9.806 Kandidaten (nur ~19K hr_companies haben Website/Domain — deutlich unter 170K-Schaetzung). Test-Hit-Rate 48% (23/48), Live-Briefing 56.9% (107/188).
ND — Domain-Resolver hr_companies 3-Phasen-Waterfall 12.04.
scripts/domain_resolver_hr.py — Phase 1 GMaps-Trigram-Join (gmaps_discoveries.name, GIN lower() gin_trgm_ops Rebuild, threshold 0.6, ~300 Matches pro 1K-Chunk = 30%). Phase 3 job_advertisements-Join (company_domain via Trigram, DISTINCT ON). Phase 2 Daemon Name-Heuristik mit HTTP-HEAD-Verify (Rechtsform-Suffix-Strip, Umlaut-äöüß-Translate, .de/.com-Candidates, Parked-Domain-Blacklist sedo/dan/godaddy/afternic). Batch+Chunk-Loop über 200K-Kandidaten-Pool. Zwischenstand nach 15 Min: TMG-Backlog 9.806 → 24.208 (+147%), 13K neue gmaps_match + 1.4K kern_jobs_match in hr_companies. Alle 3 Phasen laufen parallel weiter; TMG-Extractor neugestartet.
NE + NF — EmpType-Batch + VP-Matcher Emergency-Fix 12.04.
NE: scripts/emptype_batch.sql + emptype_big.py (chunked via hashtext mod 128, statement_timeout 10min, 3s sleep/chunk). EmpType-Coverage 43% → 44.9% — die restlichen ~740K NULL-Jobs haben Descriptions ohne Marker-Wörter (Teilzeit-Desc-Step fand in 26 Min nur +107 Hits). Contact-Completer PARTITION_ID+TOTAL_PARTITIONS Env-Support, Master-P0 + W1-P1 parallel. W2 RAM 72% — Ursache: 12 Playwright-Worker für advertsdata (plan-gerecht). NF: VP-Matcher --sleep-Arg schlägt jetzt get_night_sleep() (war hardcoded 300s), 29.786 pending-Jobs ohne verwertbaren company_name (NULL/leer/Kurzform „3M“/„Db“) via Sentinel hr_company_id=-1 markiert — Monitor zeigt jetzt pending=160 statt 29.9K.
NX-70 — Landing Live-Zahlen Drift Fix 12.04.
Initial-Fallbacks in page.tsx und layout.tsx (generateMetadata) auf aktuellen Briefing-Stand gehoben: 2.280.000 → 2.306.000 Jobs, 110.000 → 103.000 neue/24h, 235K → 236K Quellen. Fetch-Logik selbst war korrekt (NEXT_PUBLIC_API_URL → /api/public/briefing, Refresh alle 5 Min). Drift entstand weil Fallbacks seit NX-63 (10.04.) nicht mehr mitgepflegt wurden — fallen nur beim ersten Render auf, danach überschreibt die Live-Response.
NX-72 — Dual TV-Dashboards (Xiaomi Mi Curved 3440×1440) 12.04.
admin/src/pages/tv.tsx — Executive TV, 60s Refresh, Hero 6-Panel (Jobs/Email/Desc/EmpType/Quality/Outreach), roter Blocker-Panel (Domain/EU Art.27/Hunter/GMaps/SendGrid), 3-Col Datenqualität/Advertsdata/Enrichment, 4-Col Bottom GVP/HR/Paid-APIs/VP-Matcher. admin/src/pages/monitor-tv.tsx — iframe-Wrapper um bestehenden /monitor plus 3 TV-Overlay-Panels (Blocker, Outreach-Funnel, GMaps-Reaktivierung). viewport=3440 / initial-scale=1 / maximum-scale=1, overflow:hidden, JetBrains Mono. Beide Pages HTTP 200.
NX-72-Final + Cluster-Fixes 12.04.
/tv Executive-Dashboard (Next.js, monitor.nip.io/tv via Nginx-Proxy :3003) bleibt. /monitor-tv-Experiment ABGEBROCHEN nach Zoom/iframe/Scale-Saga — monitor/index.html reverted auf Commit 934b4c5 + injected nur `<style>body{zoom:0.80}html{overflow:hidden}::-webkit-scrollbar{display:none}</style>`. Plus 7 ATS-Spider-Crons (bamboohr/breezy/pinpoint/icims/concludis/jazzhr/taleo) + haufe_dvinci nachgetragen (52→64 Crons). gmaps_reactivation_checker.py (Cron 08:00 + TG-Alert bei 2 Tagen <1K AD-Jobs). VP-Matcher TG-Spam gedrosselt (4h throttle + Mini-Batch-Skip + kumulative Stats). desc_booster-Ghost aus Monitor-Grid. W2 RAM-Hotfix (4 fette Playwright-Driver gekillt, 78%→66%).
NX-73 + NH-partial + W6 + Monitor-Latenz-Fix 12.04.
NX-73: Admin-Nav /gmaps-monitor + /quellen wiederhergestellt. NH Unified Company Layer (partial): unified_companies-Tabelle + 204.223 Einträge aus hr_companies (Phase 1). Phase 2 (Trigram) + Phasen 4+5 (ucl_id FK) auf 22:05 Night-Window-Cron verschoben — ALTER TABLE auf job_advertisements durch idle-in-txn Scraper blockiert. W6 Schritte 1-9: Neuer GMaps-Server 164.68.123.85 (16 vCPU/62GB/NVMe) — Docker 29.4.0, gosom/google-maps-scraper:latest-rod, 16GB Swap, UFW, Heartbeat-Daemon, Repo, .env. Monitor-Server-Grid 6→7 Zeilen. Container-Start nach 22:05. GMaps-Pause-Regel obsolet. Monitor-Latenz-Fix: Hard-Refresh-Hänger 60-120s gelöst — Root-Cause: /api/monitor/full + /api/v1/quality/* fehlten in _WARMUP_PATHS. Fixes: Endpoints in Warmup-Liste, Redis-TTL 30s→300s fresh + 1800s stale, Stampede-Lock, HEAD-Shortcut (30s→6ms), quality_tracker auf mv_dashboard_kpis + threading.Lock. Live: Hard-Refresh 49ms total. Monitor-UI Cleanup: Telegram-Sektionen weg, Beschreibungs-Coverage-Panel weg, §5 TMG als Live-Throughput-Zeile, VP-Matcher zeigt Heute/Letzte Stunde statt Prozent, GMaps-Cluster-Panel (Stellen/Firmen · E-Mail/Telefon · Neu 10min/1h), AD+GMaps Top-Bar zeigen Stellenanzeigen + X heute.
NX-75 + NH-Phase-4+5 + W6-final + Monitor True-Reach 13.04.
NH Phase 4+5 DURCH: UCL FK-Migration via pg_terminate_backend-Trick — 477k job_advertisements.ucl_id + 950k advertsdata_jobs.ucl_id (96% Coverage). Batched mit SKIP LOCKED gegen Deadlocks. W6-final: 25 Container dediziert (statt 8), W1+W2 gmaps-systemd-services disabled (waren Auto-Restart-Verursacher), gmaps_csv_watcher auf W6 deployed (fehlte!). NX-75 True-Reach-MV: mv_gmaps_true_reach (vp_jobs 234k + ad_jobs 108k = combined 341k). Landing companies 409k→642k. NX-75b/c Monitor-Vereinfachung: Additive Kacheln (Jobbörsen + ATS + AD + Sonstige = Aktive Stellen). mv_firmen_distinct (5 Quellen: 642k distinct). mv_source_buckets mit Primary-Attribution + heute-Werte. Firmen Entdeckt 362k Bucket. Matcher-Fix: mv_matcher_stats ersetzt 7× COUNT FILTER (war statement_timeout → 0-Anzeige). GMaps-Rate: live aus gmaps_results_raw statt Batch-Import. btree-Indizes auf lower(trim(name)) für EXISTS-Lookups. 58/58 Monitor-Zellen gegen DB verifiziert, Hard-Refresh 50ms (war 60-120s). Server-Row 156px→224px (vertikal entquetscht).
NX-76 + NP-MV-Fix 13.04.
NX-76 Landing Live-Kacheln: SocialProof 4 Kacheln aus briefing (2.41M Stellen / 662k Firmen / 98.1% Direktkontakt / +246k heute). Refresh 300s→60s. Alle KPI-Werte dynamisch (auch FEATURES_10 '600k'→liveNum-Template). jobs-Prop von jobs_total auf total_active (=kern.jobs_combined) gefixt, konsistent mit Monitor. Design unverändert. Rollback-Tag pre-nx76-landing-rollback. NP-MV-Fix Monitor-Sanierung: gmaps_raw_to_discoveries.sql Bridge (*/5 min) + mv_gmaps_true_reach/mv_firmen_distinct Refresh */10 min (vorher 1×/Tag). VP-Matcher 4 alte Batch-Daemons gekillt, Bulk-Cron 4×/Tag 100k×4 Partitions. Quellen-Tile: gmaps_auto_activate Cron entkommentiert + gmaps_career_funnel Daemon gestartet. W1 6 GMaps-Container gestoppt (W6-only). Monitor-Tiles mit '=' Formel + 'ℹ' Meta-Präfix (vertriebler-freundlich).
NX-77 Firmendatenbank /firmen + NX-74-P3 13.04.
NX-77: /firmen UCL-Firmendatenbank im Customer Portal — App-Router (dashboard)/firmen/page.tsx (221 LOC, paginiert 50/Seite). Filter: Volltextsuche (debounced) + Min-Stellen + Sortierung. FirmaCard mit Jobs-Balken (VP/AD-Split visualisiert), HR-Mini-Card mit Grade-Badge, Score-Pill, Direkt-Email/Phone/Website. Backend GET /api/v1/firmen liefert 17.181 Firmen mit Jobs aus unified_companies. UCL Coverage 204k/243k hr_companies (84%). Nav-Eintrag /firmen unter Akquise & Outreach. NX-74-Phase-3: backend/hr/company/{id} returnt jetzt ucl_id (LEFT JOIN unified_companies), HR-Kontakte Firmen-Detail zeigt Gold-Pill 'Firmenprofil →' (Link auf /firma/[ucl_id]). lib/ucl.ts firmaHref-Helper. Rollback-Tag pre-nx77-rollback. Design unverändert (Plus Jakarta Sans, Blue-System).
NX-78 Customer Portal Performance-Sanierung 13.04.
Problem: /stellenanzeigen lud 30-60s ('Keine Stellen gefunden' weil Frontend-Timeout < Antwort). Root: DISTINCT ON 1.4M Jobs × 3 LEFT JOINs × 1 Uvicorn-Worker = Stau. Fixes: (1) mv_jobs_enriched (1.34M Pre-DISTINCT/Pre-JOIN-Zeilen, 7 Indizes inkl. GIN-Trigram für Search, 60d-Window, Cron */5 min CONCURRENT REFRESH). (2) Composite-Index idx_ja_dach_crawled_hr (is_dach, crawled_at DESC, hr_contact_id) WHERE is_active. (3) Uvicorn 1→4 Worker (backend_restart.sh). (4) /api/v1/stellenanzeigen/enriched komplett auf MV refactored, industry_dist separat 600s Redis-cached. (5) _WARMUP_PATHS um 5 Customer-Endpoints erweitert (stellenanzeigen + contacts + qualitaet + dashboard + top-movers). Messung: warm 33s→24ms (1250×), cold 30-60s→1.5-2s (20-30×). Rollback-Tag pre-nx78-rollback.
NX-78a TV-Monitor /tv 50" Großbild 13.04.
Eigenständige Route /tv (kein Dashboard-Wrapper, kein Header/Nav). 6-Tile 2×3 Grid mit Hauptzahlen 56px Georgia serif: Aktive Stellen (Gold), Advertsdata (Blau), GMaps (Grün), Email-Rate (Gold), Beschreibungen (Ampel ≥85% grün), GVP-Firmen (Grün). Status-Bar unten: Daemons + AD-Rate + Email% + Firmen + Refresh-Info. LIVE-Dot pulsiert grün (@keyframes tv-pulse). Auto-Refresh 30s aus /api/public/briefing. Dark-BG #0F172A, Tile-BG #1E293B. Rollback-Tag pre-nx78a-tv-rollback.
NX-79 Firmendatenbank Light Theme + 2-Spalten 13.04.
/firmen war Dark Theme (NX-77) — jetzt komplett Light analog /hr-kontakte (Referenz). 1-Spalte→2-Spalten Grid. 4 KPI-Tiles oben (Firmen/Offene Stellen/Mit E-Mail/Mit HR-Kontakt in Blau/Grün/Gold/Lila). Filter-Bar identisch /hr-kontakte. FirmaCard analog ContactCard: Firmenname blauer Link, Avatar-Initialen rechts mit Grade-Farbe+Score, Jobs-Balken VP(blau)/AD(amber), Email/Phone klickbar + Copy-Button, HR-Mini-Card mit Avatar, Footer 'Firmenprofil →'. Backend /api/v1/firmen erweitert um total_jobs/mit_email/mit_hr. Rollback-Tag pre-nx79-firmen-rollback.
NX-80 Firmenprofil /firma/[ucl_id] Light Theme 13.04.
/firma/[ucl_id] war Dark — jetzt komplett Light analog /firmen+/hr-kontakte. Seiten-BG #0F172A→weiß. KPI-Kacheln hell (VP=Blau, Advertsdata=Gold, HR-Kontakte=Grün, Quellen=Lila). HR-Kontakte Tabelle→2-Spalten-Card-Grid mit Avatar-Initialen+Grade-Farbe+EmailButton/PhoneButton. VP+AD Jobs: Cards #F8FAFC/#E2E8F0, 2-Spalten. Website-Button outlined. HRB-Badge hellgrau. Rollback-Tag pre-nx80-firma-rollback.
CLAUDE.md modularisiert 50k→3.4k 13.04.
Performance-Fix für Claude-Code (war >40k chars). Inhalt aufgeteilt: .claude/infra.md (Server/Stack/URLs), .claude/prompts.md (Prompt-Stand/Features/Rollback-Tags), .claude/data.md (Kanonische Zahlen/VP-Spaltenfallen), .claude/lektionen.md (Deployment/DB/Portal/Performance), .claude/parkplatz.md (Offene Punkte). CLAUDE.md.backup_20260413 als Sicherung. Commit d782e22.
NX-81 Personaldienstleister-Datenbank 13.04.
Eigene Portal-Sektion /personaldienstleister zwischen Firmendatenbank und HR-Kontakte. Klassifikation 3-Schicht auf unified_companies.is_personaldienstleister: Schicht 1 Name-Keywords (3.020 Treffer: personaldienstleist/zeitarbeit/recruiting/staffing/headhunter/etc), Schicht 2 industry-Match (91), Schicht 3 GVP-Member-Match (1.170) → 4.281 PDL-Firmen total (4.118 mit Jobs, 161.103 Stellen). Backend /api/v1/personaldienstleister + /personaldienstleister/kontakte (1.843 HR-Kontakte bei PDL). Frontend Light Theme analog /firmen, Tabs Firmen/Kontakte, KPI-Row, 2-Spalten Card-Grid, Copy-Buttons, Nav-Eintrag mit "Neu" Badge. Commit f7efeb4.
Advertsdata Proxy-Pipeline (IPRoyal) + Tri-State Auto-Recovery 13.04. (abend)
Hintergrund: 14:29 UTC bannte advertsdata.de die 5 Server-IPs (M+W1+W2+W3+W5) nach intensivem Scraping. tcpdump: SYN raus, kein SYN-ACK = silent drop. W6 (GMaps-only) als einzige IP noch sauber. Lösung IPRoyal Residential Proxy: 10 GB Pay-As-You-Go ($52.50/mo), Endpoint geo.iproyal.com:12321. scripts/advertsdata_proxy_scraper.py: lean requests + BeautifulSoup (~5 KB/Page statt 500 KB Playwright), Modi --gap-filler/--range/--ids, Threading + Backoff bei 403/429, Hard-Cap 9 GB. scripts/iproyal_quota_check.py: Bandwidth-Tracker, Schwellen-Alerts (50/75/90/100% ×1/Monat), Tagesreport 09:00. Tri-State Watchdog (HEALTHY/BANNED/DOWN): Direct-Check + Proxy-Check Cross-Reference, Auto-SIGSTOP/SIGCONT auf alle 5 Server, dynamisches Cron-Umschreiben (primary/fallback/off), Daily-Status 09:05. NP-B2 UCL Cross-Enrich: AD email +1.737 / phone +1.467, VP contact_company_email +175.583 / phone +176.089, UCL back-prop +2.520. Live-Test: 50/50 OK in 97s = 257 KB. Commits 6b098ce / f47232f / 7657a1f / a330501 / 701cdd5.
MV-Health-Watchdog (NX-MV-HEALTH) 13.04. (abend)
Dauerhafte Lösung gegen stale Materialized Views. Root: 4 REFRESH-Crons hatten kein PGPASSWORD → mv_advertsdata_stats / mv_matcher_stats / mv_source_buckets / mv_firmen_distinct waren bis 580 Min stale. Fix: ~/.pgpass + alle Crons mit PGPASSWORD=. NEU scripts/mv_health_check.py: scannt 18 MVs alle 10 Min via refreshed_at-Spalte oder Filesystem-mtime. Pro MV erwartetes Refresh-Intervall (2-30 Min). Stale (>3× erwartet) → Auto-REFRESH (CONCURRENTLY mit Fallback non-concurrent). Telegram-Alert bei Fehler (1h Cooldown pro MV). Daily-Report 09:10. Plus 4 UNIQUE INDEX auf refreshed_at für alle 4 betroffenen MVs (vorherige (1)-Expression-Indexe waren für CONCURRENTLY ungeeignet). Crons: */10 auto-refresh + 09:10 daily-status. Commit c0e5a47.
Monitor-Refactor: TG-Live + IPRoyal-Tile + Paid-APIs-Top 13.04. (abend)
Telegram-Bot Live-Fenster rechts unten (col 7, row 2-3, volle Höhe bis HR-GVP-Ende): DB-Tabelle telegram_message_log + Patch in telegram_utils._send_raw persistiert jede gesendete Nachricht (fail-silent). Backend _read_telegram_log(20)telegram_log-Feld in /api/monitor/full. Frontend rTgLog(): scrollable Liste, kategorie-farbig (rot=critical, amber=watchdog, gold=quota, violett=mv_*, grün=daily), relative Zeit. Layout: Paid APIs+IPRoyal jetzt rechts oben (col 7, row 1) statt unten, Live Throughput ausgeblendet. IPRoyal-Tile: zeigt MB statt 0.00 GB bei kleinem Verbrauch, 1px-Mindest-Bar. Grid-Compactness: grid-template-rows minmax(170/190/190px, max-content) + align-content:start — kein Freiraum mehr zwischen Enrichment↔Matcher und Signals↔HR-GVP. Commits 4fbf015 / 123820b / 59791ad / c0e5a47.
NP-C BA-API-Fetcher löst Playwright ab 13.04. (nacht)
Root-Cause: 675.888 Jobs als description='[nicht extrahierbar]' markiert (557k davon BA). Playwright-Fetcher hatte nur 3% Hit-Rate — ~50% BA-Jobs sind expired (404 auf SPA-Shell) + Anti-Bot auf den Rest. Lösung: offizielle BA REST-API https://rest.arbeitsagentur.de/jobboerse/jobsuche-service/pc/v4/jobdetails/{base64(job_id)} mit Header X-API-Key: jobboerse-jobsuche, Response-Feld stellenangebotsBeschreibung. scripts/ba_api_fetcher.py: aiohttp + 15 concurrent, 2000/Batch, ~100/s Throughput, 65% OK / 35% expired (404 → description='[expired]' + is_active=false) / 0 Err bei c=15. ETA: 557k Backlog in ~1.5-2h durch. KPI-Impact: jobs_combined 2.431k → ~2.225k (-206k expired deaktiviert), desc_pct 50.3% → ~75-80%. Swap: alter ba_description_fetcher gestoppt (PID 715779), Cron live + crons/master.crontab*, 10 Refs geswappt (main.py, admin_api.py, heartbeat_sender, auto_healer, telegram_control_bot, critical_alert, pipeline_wakeup_checker, briefing_auto_analyst, tis_scanner, never_idle_monitor). Admin-Daemon-Label: "BA-API-Fetcher / BA REST-API (110/s, 65% OK) / master".
NP-C2 Workday-API-Fetcher 13.04. (nacht)
Analog BA-API: scripts/workday_api_fetcher.py, nutzt /wday/cxs/{tenant}/{site}/job/{path} statt Playwright. Site-Fallback ExternalCareersExternal_Career_Site. Result: 36/s, 72% OK, 5% expired, 23% unbekannte site-slugs. Backlog: 23.119 Workday-Jobs als [nicht extrahierbar] → ETA ~11 Min. Cron */10, LoadGuard. Alter workday_desc_fetcher.py hatte 0% Hit-Rate (Regex-Bug: erwartete {career_path}/job/ statt /job/).
NX-83 HR-Matcher Benchmark 14.04. (nacht)
Phasen 1-4 durchgeführt. scripts/hr_matcher_benchmark.py Zwei-Phasen (Sustained 3.3/s + Burst 100/s, 2x1000 Rows). Ergebnis: ELASTISCH Faktor 0.55x (Burst schneller als Sustained, Matcher batch-polling kein LISTEN/NOTIFY). p50 Sustained=358s / Burst=183s, p95=381s/210s, 100% Completion. docs/matcher_capacity.md + Alert-Thresholds (pending>500 warning, >2000 critical). Commit a114e1b.
TV-Monitor für Samsung U7000F 65" 4K 14.04.
Zwei Dashboards für 4K 3840×2160 Showroom-TV optimiert. Monitor (monitor.*.nip.io): CSS Media-Queries body{zoom:1.3} bei ≥2560px und body{zoom:1.8} bei ≥3200px (NX-72-konform, kein scale/iframe). Admin /tv (frontend/src/app/tv/page.tsx): tileValue 56→104px, Labels 22→34px, Grid-Gap 20→32, Padding generos, Box-Shadow für Premium-Look.
Cluster-Optimierung 14.04. (vormittag)
Plan-basierte Stufen 0/1/2/6 umgesetzt. Stufe 0: 64 SIGSTOPPED AD-Procs clusterweit gekillt, ~86 GB RAM freigegeben (W5: 33→0.8 GB). Stufe 1: GMaps Queue-Reset, W6 15/25 Container stabil. Stufe 2: Description 8-Shard Setup M(0)+W1(1,2)+W3(3,4)+W5(5,6,7), +60% Throughput (76k desc/h, backlog 688k→129k in 25min). Stufe 6: w4_load_alert.py */5min Telegram. W1-Zombie-Intervention: 25 gmaps-worker-Container vom docker_watchdog auto-restarted, Load 354. Fix: docker_watchdog Cron-Line entfernt, Container gewiped, Load 354→10. Stufe 3+5 canceled (Generator saturiert / W4-Schutz). Stufe 4 pending (IPRoyal-Upgrade-Entscheidung).
NX-GM-P1 GMaps Full-Matrix 14.04. (vormittag)
GMaps-Inventur: 258 keywords × 869 cities = 224k theoretische Tuples, nur 122k in DB (54.8%). Neue Strategie 4 in gmaps_query_generator_v3.py reiht die 161k offenen Kombinationen ein (prio=3, nach S1-S3). Default OFF (env GMAPS_FULL_MATRIX=1). Historische Yield: median 2 Firmen/Query → Prognose +320-480k Firmen in 4-7 Tagen bei Aktivierung. gmaps.total 438k → ~800k. Bundle C wartet auf Sandro-Freigabe.
NX-83a + NX-DR + NP-A2 + NP-E + NP-F — Daemon-Resilience-Stack 14.04.
NX-83a (4696025): HR-Matcher Color-Tile + Cron-Alert (≥2000 pending, 30min Grace/1h Cooldown). NX-DR (0e62d19): scripts/db_utils.py mit TCP keepalives + reconnect_on_drop + ResilientConn; daemon_keeper v2 cron */5→*/1 mit diagnose() (Log-Tail+OOM im Telegram-Alert); Monitor-Kachel OFFLINE pulsiert rot (vp-offline-pulse). NP-A2 (be288f8): PDF-Extractor via IPRoyal-Proxy (Direct-Fetch HTTP:000 Bann, via Proxy HTTP 200), pdf_last_try_at + Retry-24h + resilient, Cron 02:00→*/30. NP-E (2df7f1d): description_daemon --shard required=True + endless-reconnect + per-shard-log logs/description_daemon/shardN.log + mini-batch-commit je 50 Rows. NP-F (9d741c7 + 317d003): Root-Cause fuer weiterhin-crashende Master/W1/W3-Shards — worker_scheduler.py */5 (kill -9 pgrep description_daemon) + worker_watchdog.py */10 W1+W3 (os.kill) + crontab default-shell /bin/sh kennt kein source (NP-D/NP-A2 Cron-Lines brachen stillschweigend). Alle 3 deaktiviert + SHELL=/bin/bash. Alle 8 Shards stabil (W5 50min, W3 28min, M 28min, W1 19min). 11 neue Lektionen in .claude/lektionen.md.
NP-G — Abend-Marathon Stabilität+Pipeline+Outreach+Doku 14.04.
8/8 Shards stabil, PDF-Extractor+Adzuna Crons verifiziert, Sandro-Briefing erstellt, docs/sandro_briefing_14apr.md.
NP-H/H2/H3 — Backend-Performance 5-30s→0.02s 14.04.
Monitor-Endpoint _get_all_daemon_status live-override 5-12s, telegram-log TTL 3s, uvicorn multi-worker In-Memory-Cache Antipattern, Frontend fresh=1 hardcoded. Fixes: Redis-shared Caches + fresh=1 raus. 250× schneller.
NP-I — Portal In-Memory→Redis Migration + 404-Fix 14.04.
3 weitere Caches auf Redis migriert (_ext_monitor_cache, _full_status_cache, _snapshot_cache), /api/quality/dashboard 404→korrekte Route /admin/api/iq/quality-dashboard.
NP-J — Briefing Stampede-Lock 14.04.
Cold-Miss Stampede: alle Worker bauten parallel → Nullen im Dashboard. Fix: Wait-Loop (500ms×80 polling), Lock SET NX EX 90, Stale-Fallback. 5× parallel = alle mit Daten, keine Nullen.
NP-K — Code-Audit Fixes 14.04.
fresh=1 Survivors in TV-Seiten bereinigt, 6 Scripts auf db_utils migriert, useBriefing Retry-Logic, BRIEFING_FALLBACK aktualisiert.
NP-L — Customer Portal Briefing-URL Fix 14.04.
useBriefing.ts nutzte NEXT_PUBLIC_API_URL (mit /api/v1 suffix) statt API_BASE → doppeltes /api/v1/api/public/briefing = 404. Fix: API_BASE ohne Suffix.
NP-M — v1-Endpoints Redis-Migration 14.04.
cache.py Helper (redis_cache_get/set/stale), dashboard_overview+placement+hr/contacts auf Redis-shared. IPRoyal State korrigiert.
NP-N — Stampede-Lock cache.py + admin_api Redis + IPRoyal 14.04.
redis_cached()/redis_cached_async() mit Lock+Wait-Loop+Stale. admin_api.py Redis-backed. IPRoyal 15 GB Plan, PDF-Extractor auf 0 */4. 5 Zombie-PDF-Prozesse gekillt.
NP-P/Q/R/S/T — Telegram-Spam, Worker-Perf, IPRoyal-Reset, Bandwidth, Watchdog 15.04.
NP-P idle_txn_killer Category-Fix. NP-Q ATS-Timeouts 600s + salary_extractor env-DSN + 7 Regex. NP-R IPRoyal 10 GB reset. NP-S Telegram 9 Categories + Bandwidth-Faktor 1.3→8. NP-T iproyal_budget_watchdog */5 Auto-Stopp 90%.
PIPELINE-BALANCE 17.04. (21:25) — CC Aging-Bias + Auto-Solver-Tuning
Commit 2832eab: User-Trigger "Email-Pct stagniert 65.1%, W4 Load 12.9 trotz Auto-Solver". 591k Jobs > 7d alt verhungerten im CC-Backlog.
Teil 1 Auto-Solver-Tuning: LOAD_THRESHOLD 12→8 (W4 hat 8 vCPUs, Load 8 = 100%). fix_idle_in_tx() Whitelist: application_name NOT ILIKE '%enricher%' + query-pattern Filter (contact_company_email/phone) → verhindert Termination legitimer Enricher-SELECT→HTTP-Cycles (Lektion #65/#67-Schutz).
Teil 2a Contact-Completer 70/30: 2 Sub-Queries — 70% fresh (<7d, DESC) + 30% aging (>7d, ASC). ORDER BY hashtext(id) %% 10000 Sampling auf 591k Rows war zu teuer (statement_timeout 30s+, Seq-Scan). Lösung: ORDER BY crawled_at ASC nutzt vorhandenes idx_jobs_active_crawled → Index-Scan 38ms. Live-Verify: Batch: fresh=350 + aging=150 = 500.
Teil 3 Zufluss-Analyse: Discovery-Crons bereits konservativ (1×/Tag) — kein Drosseln nötig. Hauptzufluss ats_recruitee 1426/h ohne Email = spider-driven, nicht discovery-driven. Aging-Bias ist primärer Lever.
Worker-Sync: contact_completer + w4_auto_solver auf W1+W2+W5, daemon_keeper restartet binnen 1min. Lektionen #90 (Aging-Bias Index-Scan) + #91 (LOAD_THRESHOLD = vCPUs).
ENRICHER-RECOVERY 17.04. (21:00) — Heartbeat-Partitionen + W4-AutoSolver
Commit 3b8c49b: User-Trigger "Email-Pct 78.7%→65.1% Absturz, Throughput 259/h statt 19k/h, W4 91% CPU". 4 Teile + Bonus-Fix:
Teil 1 Heartbeat-Partitionen: heartbeat_sender.EXPECTED_DAEMONS 1:1 mit daemon_keeper — alle _pN.sh-Wrapper individuell trackbar (vorher generic Pattern → keine Partition-Crash-Detection). W1 +6, W2 +4, W3 +4, W5 +8 Wrapper. Sync 5 Worker.
"6 offline"-Bug-Fix (Backend-Normalisierung): Heartbeat schreibt _pN.sh in daemons_running-Set. Backend ALL_DAEMONS hat generic Names. Set-membership 'phone_enricher' in {'phone_enricher_p0.sh',...} = False. Fix in _get_all_daemon_status(): re.sub(r'_p\d+\.(sh|py)$','',x) → base-name auch ins Set. Verify: Online 27 | Offline 0 (vorher 6 offline). Lektion #88.
Teil 2 W4 Auto-Solver scripts/w4_auto_solver.py Cron */2: (a) pg_terminate_backend WHERE state='idle in tx' >60s, (b) wenn >2 parallele MV-REFRESHes → jüngste terminate, (c) bei load > 12 VP-Matcher pkill (daemon_keeper restartet). Telegram-Alert nur bei Action. Live-Verify: W4 Load 12.27 → 9.87 in 5min, killed_idle_tx=1. Lektion #89.
Teil 3+4 implizit: alle 27 Daemons online, Throughput 259/h → 615/h (2.4×), Phone-Enricher bereits max-config. CC-Backlog 591k > 7d alt → eigene Iteration.
AP4-COMPLETION 16.04. (18:40) — Frontend-Tiles + IPRoyal-Fix + LLM-Classifier + Quad-Sync
Closes the loop on AP4 (Lektion #82: Backend ohne Frontend = unsichtbar). IPRoyal-Tile-Fix in main.py:_read_iproyal_quota(): 2-Tier-Lookup (Tabelle iproyal_budget_history bevorzugt → State-File mit OVERHEAD_FACTOR=2.16 Fallback). Source-Indikator (state_file_corrected/iproyal_budget_history). Live-Verifikation: used_gb 4.875 → 2.257 GB. Monitor v6.7 (monitor/index.html): Grid-Row 4 mit 3 neuen Tiles + JavaScript-Loop alle 30s — (1) 📊 Pipeline Trends 48h (4 SVG-Sparklines: email_pct/desc_pct/phone_pct/quality_avg) via /api/monitor/trends, (2) 🌐 IPRoyal Burn-Rate 7d (SVG-Liniendiagramm + cap-Linie + Forecast) via /api/monitor/iproyal, (3) 📋 Audit 48h (Top-Categories Table mit ACTION_REQUIRED-Markierung) via /api/monitor/telegram-audit. Footer-Bump v6.6→v6.7. LLM-Classifier W2 scripts/telegram_audit_classifier.py: Claude-Haiku-4.5-API, BATCH=50, MAX_BATCHES=4, self-contained (chdir + .env-Loader). Cron 0 */4 auf W2. Smoke-Test: 12 Alerts klassifiziert (5 INFO, 4 FALSE_POSITIVE, 2 ACTION_REQUIRED, 1 INFO). Phase 4.2 Quad-Sync scripts/daemon_config_sync_check.py: 4-Way-Sync keeper↔heartbeat↔main.py↔critical_alert. Norm-Helpers: Partition-Wrapper auf Basisname, Shard-Suffix gestrippt, main.py nur auf Master. Cron */30 auf W2. 2 echte Drifts erkannt auf W1+W5 (heartbeat_sender.EXPECTED_DAEMONS fehlen 4-5 Enricher). Phase 4.3 Heartbeat-Completeness scripts/heartbeat_completeness_check.py: vergleicht heartbeat_sender vs. worker_heartbeats.daemons_running. Cron */15 auf W2. Smoke-Test: alle 6 Worker 100% Coverage. NOTIFICATION_CONFIG +6 Categories auf alle 5 Worker synced. Lektionen #84+#85+#86 neu.
AP4 Monitor+Observability Meta-Layer 16.04. (17:25)
Commits afbe610+a39b4ce: 5-Phasen Meta-Layer, Collector-Worker W2. Phase 1 Metriken-Zeitreihen: pipeline_metrics_hourly + 11-Metriken-Collector (Cron hourly). Phase 2 Telegram-Audit: telegram_audit-Tabelle + send_alert-Hook. Phase 3 Deploy-Drift-Audit: md5-Vergleich Master↔5 Worker (Cron */4h). Phase 4.1 Code-Freshness: mtime(script) vs. starttime(proc) (Cron */15). Phase 5 IPRoyal Burn-Rate mit 3-Tier-Fallback (API→Playwright→state_file, Skeleton-Mode aktiv). 3 neue API-Endpoints: /api/monitor/{trends,iproyal,telegram-audit}. Sofort-Befunde: 4 stale Daemons + 5 Worker mit Drift gefunden. Follow-ups: Playwright-Install auf W2, LLM-Classifier (Claude API), Frontend-Sparkline-Tiles, Phase 4.2/4.3.
SHF-ADVERT: PDF-Extractor Daemon-Mode auf W3 16.04. (16:57)
Commits e46fab2+2eebba4: Umstellung von Master-Cron 30 2 * * * auf daemon_keeper-verwalteten Daemon auf W3 (Load 1.84, 45GB RAM frei). 4-Way-Sync (Lektion #50): daemon_keeper EXPECTED + heartbeat_sender EXPECTED_DAEMONS + main.py ALL_DAEMONS + critical_alert WORKER_DAEMONS. PyMuPDF (fitz) nachinstalliert auf W3 via pip --break-system-packages. DB_HOST=161.97.79.192-env explizit gesetzt im restart-Command. Live-Betrieb: 295 PDF-Extractions in 10min, State-File unverändert (Cache-Extraktion, kein neuer Proxy-Traffic). Kill-Recovery-Test: pkill + 75s warten → daemon_keeper (Cron */1 auf Master) hat automatisch restartet. Neue Lektion #80 (Logger-Duplizität ist false-positive von Lektion #71/#76 Doppelstart — hier FileHandler + StreamHandler + 2>&1-Redirect).
NP-P2: EURES Skeleton (API blockiert) 16.04. (16:30)
Commit bb0be2c: EURES Public-API seit Portal-Rewrite 2024/2025 nicht mehr ohne Auth zugänglich. API-Discovery testete 4 Endpoints: alle 401/403/404. scripts/eures_fetcher.py als Skeleton angelegt: API-Discovery-Loop + Safe-Abort bei unerreichbarer API (Telegram-Warning + Exit 0, keine DB-Inserts). Script ist Auth-Ready via EURES_API_TOKEN env-var — Re-Enable ohne Code-Change wenn API wieder öffnet. Kein Cron installiert (wäre Telegram-Spam). DACH-Abdeckung ausreichend via BA-API (744k), Adzuna (161k), Arbeitnow (1.1k) = 906k Jobs. Neue Lektion #79 (API-Discovery + Skeleton-Pattern).
NP-P3: Arbeitnow Fetcher live 16.04. (16:23)
Commits e8e23a6+494b0b8: Neuer Public-API-Fetcher für Arbeitnow.com (Berliner Job-Board). scripts/arbeitnow_fetcher.py angelegt, Schema auf echtes job_advertisements adaptiert (content_hash statt job_uid, position statt title). Full-Run: 1.051 Jobs in 40s, 100% desc-coverage, 165 Remote, 556 mit employment_type. API liefert real ~1.1k (nicht 50-100k wie Prompt erwartete). Cron 0 */6 installiert mit cd-Prefix. UPSERT-Pattern konform zu Lektion #78 (DO UPDATE SET crawled_at=NOW()).
NP-P1: BA-API-Backlog bereits erledigt 16.04. (16:20)
Commit bd0da86: ba_api_fetcher läuft (PID 1371505). Backlog 7.7k → 116 (98.5% Reduktion seit Prompt-Erstellung). Total BA-Jobs: 744.023, davon 743.907 mit Description = 99.98%. 88 residual permanent-nodesc (BA-API liefert für diese Jobs keine Description). Keine Code-Änderung nötig, Config war optimal.
AP3 Phase 1: Email-Boost ×21 16.04. (16:10)
Commits 8dd673e+c3e096c: Baseline 64.8% email_pct mit 894 enrichments/h → 23 Tage bis 80%-Ziel. Fix: BATCH_SIZE (domain_email_booster 500→1000, career_email_miner 500→1000) und 2.5× (ats_email_enricher 200→500). rsync 5 Worker + pkill für daemon_keeper-Auto-Restart. Messbare Wirkung nach 15min: emails/10min 150→3.188 (21×), desc/10min 710→3.542 (5×). Neue ETA 80%-Ziel: 11h statt 23 Tage. Phase 0 AP2-Lücken bereits durch AP3-P0 (15.04) erledigt. Phase 2 Phone schon maxed (BATCH=1000, CONCURRENT=80). Phase 3 Desc ETA 4h. Phase 5 VP-Matcher 839k pending mit Trigram-Timeout — separater Follow-up p_ats_matcher_optimize.
UPSERT-Batch-Fix: 27 Scripts 16.04. (15:45)
Commit 7bb0034: System-weiter Audit legte offen dass praktisch ALLE ATS-Core-Spider (personio/greenhouse/lever/join/breezy/pinpoint/softgarden/workday) + 19 weitere Scripts den UPSERT-crawled_at-Bug hatten. Batch-Fix via Python-Regex für 27 Files (ATS-Scripts, ATS-Core-Spider, generische Spider, Pipeline, Utility). Syntax-Check grün, rsync auf 5 Worker. Löst auch den bei p27 vermuteten Upsert-Bug bei personio/softgarden/lever. Lektion #78 erstellt.
UPSERT-crawled_at-Bug Fix (dvinci/icims) 16.04. (15:35)
Commits 6cad19c+3e14922: User-Meldung "dvinci im Monitor rot" legte einen lange latenten Upsert-Bug offen. Spider fand 884 dvinci-Jobs, DB schrieb nur 6 neue Rows. Root-Cause: ON CONFLICT (content_hash) DO UPDATE SET last_seen_at=NOW(), is_active=true — aber crawled_at wurde nicht mit-upgedatet. Konsequenz: Bei Duplikat-Crawls (selber content_hash) bleibt crawled_at beim ersten-Insert-Zeitpunkt → Monitor-Query MAX(crawled_at) > NOW()-48h erkennt Spider als "tot" obwohl er aktiv läuft. Fix: DO UPDATE SET last_seen_at=NOW(), crawled_at=NOW(), is_active=true in crawl_haufe_dvinci.py:50 + icims_spider.py:228. rsync auf 5 Worker (md5 identisch). Re-Run: dvinci 6→358 inserts/10min ✔, MAX crawled_at 13:27→13:33 UTC. Monitor grün: last_48h=358 (>> Threshold 20). Lektion #78: Audit-Befehl grep -rn "ON CONFLICT.*DO UPDATE" | grep -v crawled_at für weitere Spider-Audits. Das ist auch die bei p27 vermutete Upsert-Ursache bei personio/softgarden/lever!
SHF-ATS icims+dvinci ResilientConn-Deploy 16.04. (15:25)
Commit df932b8: 2 weitere ATS-Spider (icims seit 15.04 10:08 stumm, dvinci seit 15.04 10:44) auf ResilientConn migriert. Master-Syntax-Check grün, rsync auf 5 Worker (2 Files × 5 = 10 Transfers, db_utils.py war bereits identisch — md5 534240513821bd...), Remote-Import-Test auf allen 5 Workern grün. Smoke-Test: icims findet Actalentservices 20 jobs + Bridgecrestsuites 5 jobs + 404-Handling; dvinci iteriert 884 Jobs erfolgreich. 0 OperationalError + 0 InterfaceError. Beide laufen via Master-Cron 0 12 + 30 12 daily — kein Daemon-Restart nötig.
SHF-P03v3: IPRoyal Final Fix mit PID-Lock 16.04. (15:15)
Commit c81a65a: Permanent-Fix für Budget-Emergency. PID-Lock via fcntl in advertsdata_pdf_extractor.py:_acquire_singleton_lock() — Aufruf als erste Zeile in _safe_main(). Lock-File /tmp/advertsdata_pdf_extractor.lock. Sanity-Test: erster Start OK, zweiter Start liefert Lock belegt — andere Instanz läuft. Abort. Exit 0. Cron konsolidiert: genau 1 PDF-Cron (30 2 re-enabled mit Lock-Safety) + 1 Proxy-Cron (0 */6 --limit 2). AD-Cluster-Klarstellung: Watchdog meldet inserts/60min=0 seit 15:05 — das ist by-design nach Emergency-Drossel (8 Jobs/Tag, 6h-Intervall). BANNED-Flag des Watchdogs irreführend bei Emergency-Config, Follow-up zum adjust. Lektionen #76+#77 (umnummeriert wg. Konflikt mit paralleler Session zu ATS-Inventur) als gefixt markiert.
p28 v2: GMaps-Daemon Restart W6 16.04. (14:45)
Commit fde1746: Handoff Follow-up #3 erledigt. Gleiches Muster wie p27: gmaps_daemon-Prozess lief 19h mit alter 20000/14400-Config obwohl p28-Fix (3000/3600) seit 13:28 auf Disk lag. Log bestätigte: [11:16:27] Turbo-Lauf #12 startet (20,000 Queries). Actions: pkill gmaps_daemon + gmaps_turbo + docker stop/rm aller 13 Container + Queue-Reset UPDATE gmaps_jobs SET status=pending WHERE status=running (14.800 rows). daemon_keeper */1 restartete automatisch → neuer Daemon PID 2559721 (14:41:54). Log: [14:41:54] === Turbo-Lauf #1 startet (3,000 Queries) === ✔ NEUER CODE AKTIV. Docker-Worker spawnen, Queue 15000→9000+6000 in <10min.
p27 v2: ATS-Daemon 40h+ stuck — Root-Cause-Fix 16.04. (14:30)
Commit a335f14: ats_crawler_daemon auf W1 lief seit 14.04 mit ALTER Code-Version (Prozess-Alter ≠ Code-Alter). Nach Force-Restart: No module named crawler.spiders.ats.join_spider. Master hatte 11 Spider im Dir, W1 nur 7 — join_spider.py, breezy_spider.py, pinpoint_spider.py fehlten. Alle 6 Spider-Imports im gemeinsamen try-Block → 1 fehlt = 5 andere skippen = stuck-state 40h+. Fix: rsync vakanzpuls/crawler/spiders/ Master→W1 + Daemon-Force-Restart. Spider laufen wieder: Hogast 7 Jobs, Minor Figures 3, Viataurus 12. Pending-Counter 23.699→22.896 in 4 Zyklen. Zweites Problem: 0 DB-inserts für personio/softgarden/lever trotz gefundener Jobs → UPSERT-Bug separat zu fixen. Lektionen #73 (Prozess≠Code) + #74 (try-Block All-or-Nothing) + #75 (Deploy-Drift-Audit).
p16 v2 Re-Verifikation: Monitor-Stack stabil 17.04. (14:25)
Commit 4468bfb: monitor_health_alert.py:check_idle_txn() mit ResilientConn + statement_timeout=5s live. Smoke-Test 5× green: monitor/full 0.07s, briefing 0.00s, tg-log 0.01s, idle-tx OK, remote 0.02s. External HTTPS 5× parallel 0.013-0.019s (DoD <5s um Faktor 250× unterboten). 0 KRITISCH-Alerts in 30min (vs. 95+ in Ausgangslage). Audit: kein Monitor-Script nutzt noch psycopg2.connect direkt. Follow-up bleibt Cold-Miss-Refactoring (Parkplatz #45) + Backend Legacy-Router (Low-Prio, SQLAlchemy bereits resilient).
BUDGET-EMERGENCY 17.04. (14:15) — PDF-Extractor Doppelstart
Commit 7655d2f: IPRoyal fiel 5.02→4.55 GB remaining in 20min. Root Cause: PDF-Extractor lief DOPPELT (Cron 30 2 + 0 14), zusätzlich lief der 02:30-Prozess 11h statt zu terminieren (MAX_BATCHES=5 respect-issue). Log zeigte jede Zeile doppelt als Indikator. Sofort-Fix: pkill aller PDF-/Proxy-Prozesse, beide PDF-Crons auskommentiert, Proxy */15 --limit 250 */6 --limit 2 = 184 MB/Tag Safe-Rate. 14 Tage × 184 MB = 2.6 GB, Puffer 1.9 GB bis 01.05. Cron-Backup /tmp/crontab_pre_budget_emergency.bak. Lektionen #71 (PDF-Doppelstart-Detection) + #72 (Counter-Overhead ≠ Volumen-Problem).
p09 v2 Re-Verifikation: awo/caritas-Audit 17.04. (14:10)
Commit 451e344: Situation stabil und leicht verbessert. 888/907 Sources aktiv (97.91%), 829/888 in 24h erfolgreich gecrawlt (93.4% Crawl-Coverage). DNS-Tests bestätigen: jobs.awo.org + jobs.caritas.de weiter tot (seit >3 Wochen), 4 zentrale Sources bleiben korrekt deaktiviert. Caritas-Nachfolge-URL liefert HTTP 200, aber ohne Schema.org JSON-LD → separater Parser nötig. Keine Aktion erforderlich. Empfehlung: Status-Briefing-Wording anpassen (Lektion #69: Zentral-Jobbörse vs. Einzelstandort differenzieren).
p03 v2 + Handoff Follow-up #1: IPRoyal-Drossel 17.04. (14:05)
Commit c5fad17: Cron --limit 75→25 (Budget-kritisch, pre-drossel war 27 GB/Tag bei 9 GB-Budget). Zusätzlich entdeckt: IPRoyal Dashboard zeigte 4.98 GB used, unser State-File zählte 8.05 GB → echter Overhead-Faktor empirisch 2.16× (nicht 3.5). State auf IPRoyal-Ground-Truth gesetzt (4.98 GB = 55% von 9 GB Cap). Code-Faktor 3.5 bleibt als Safety-Puffer (konservativ = budget-safe). inserts/60min = 155 ✔ Scraper liefert. Rest-Budget 4.02 GB für 15 Tage = 268 MB/Tag Safe-Rate.
p15 v2 Re-Verifikation 17.04. (14:00) — PgBouncer harte Zahlen
Commit d87e5b9: Live-Verifikation der 16.04-Änderungen. Pre-p15 (00:00-13:15): 19.847 query_wait_timeout Events (~25/min Flood). Post-p15 (13:18-14:00): 0 Events in 45min clean. Pool-Auslastung jetzt 65/200 vs. vorher 31/40 blockiert. Config-Diff bestätigt: default_pool_size 40→80 + server_idle_timeout 600→1800. Backup pgbouncer.ini.20260416_131555.bak bleibt für Rollback. Wichtig: PgBouncer läuft auf Master (161.97.79.192), nicht auf W4 — die W4-Instanz läuft zwar, aber mit 0 xacts/s (ungenutzt).
p05 v2 Re-Verifikation 17.04. (13:55) — nach Handoff
Commit 2e5a2a3: Nach Session-Handoff 4 parallele Smoke-Tests (5min cap). breezy 179 Firmen, pinpoint 195 Firmen, jazzhr 35 Jobs (exit 0, 97s), bamboohr DIAG 449 OK / 28 JSON-Fail (HTML-Redirect) / 6 HTTP-401. 0 Tracebacks, 0 OperationalError, 0 DB drops über alle 4 Scripts. ResilientConn-Decorator blieb transparent — kein Retry nötig, weil PgBouncer-Pool 80 (nach p15) ausreichend. Validiert p15+p16 Wirksamkeit: Pin #95 seit 15h clean. bamboohr-Schema weiter unverändert ({meta, result:[...]}) — HTML-Detection-Patch bleibt für eigene Iteration p_bamboohr_html_detect.
Shadowfix-Session 16.04. (13:45) — 7 Prompts abgearbeitet
Commit 49a310c: Parallele Session (nicht CC) hatte p0.1/p0.2/p1.4 + IPRoyal-Counter 8→3.5 + Statusbericht vorbereitet. CC arbeitet 7 Shadowfix-Prompts ab. p15 (Root-Cause-Fix): PgBouncer default_pool_size 40→80 + server_idle_timeout 600→1800. Diagnose: pooler error: query_wait_timeout-Flood, 21 idle-in-tx + 10 active = 31/40 Slots permanent blockiert. Fix eliminierte Pin #95 "KRITISCH: Datenbank nicht erreichbar" (95+ Events → 0 neue in 30 min). p16: monitor_health_alert.py:check_idle_txn() auf ResilientConn + statement_timeout=5s. Backend SQLAlchemy pool_pre_ping bereits resilient. p05: 5 Scripts Syntax-Check + breezy/pinpoint/jazzhr/bamboohr Smoke-Tests. bamboohr DIAG: Schema unverändert ({meta, result:[]}), niedrige Job-Rate durch Source-Churn (HTML-Redirects auf Landing). p03: Bandwidth-Counter 9.02 GB→0 reset, manueller Testlauf 5/5 saved, Faktor 3.5 bestätigt. p09: awo/caritas-Deaktivierung korrekt (DNS-fail der 2 Zentralbörsen), 878/899 Sources (97.7%) aktiv, Status-Briefing-Wording irreführend. p28: gmaps_daemon.py QUERIES_PER_RUN 20000→3000 + timeout 4h→1h + Queue-Reset bei TimeoutExpired. Deploy auf W6, greift bei nächstem Daemon-Restart. p27: Baseline erfasst — nur ats_personio (0/24h, 40h stuck), softgarden/greenhouse/lever/BA liefern normal. 24h-Recheck 17.04 13:42. Lektionen #68 (pool_size vs. idle_timeout), #69 (Zentral-Jobbörse vs. Einzelstandort), #70 (gmaps Chunking-Kalibrierung). Reports .claude/report_shadowfix_p*.md.
career_email_miner + data_propagator Nachbesserung 16.04. (00:30)
Commit b66b02f: career_email_miner schließt Read-Connection VOR dem HTTP-Crawl-Loop, nutzt frische write_conn für UPDATEs — eliminiert auch die letzte idle-in-tx-Quelle. Commit 951b487: data_propagator get_db() bekommt 3× Retry mit exponential Backoff gegen PgBouncer-Drops. Deploy auf alle 5 Worker via deploy.sh, Daemons gekillt → daemon_keeper restartet mit neuem Code. Plus Remote Trigger trig_017zpP8geoKWYxQ3gtREk9VC (VP Nightly Health Check) für 02:30 UTC täglich.
NP-AO-v7b — idle-in-txn Final-Fix 16.04.
Monitor-Flicker (0 Jobbörsen/ATS) verursacht durch career_email_miner: Connection hielt Transaction 5+ Min während HTTP-Crawl → PgBouncer-Slot blockiert → monitor/full timeoutet. Fix: conn.commit() nach cur.fetchall() in career_email_miner (Z.109) + contact_completer (Z.107) + data_propagator get_db() in try-Block + main-Exception-Handling für Reconnect-Safety. Deploy auf alle 5 Worker. Lektion #67: conn.commit() nach SELECT Pflicht wenn danach HTTP-Loop folgt (Unterschied zu #65 async: gilt auch synchron).
AP3 Phase 0 — AP2-Lücken: vp_matcher + briefing_analyst 15.04. (Abend)
Zwei Scripts die in der Batch-Migration nicht erfasst waren. (0.1) advertsdata_vp_matcher_daemon.connect(): eigene Funktion → nutzt jetzt _dbutils_connect(DB_DSN) + SET statement_timeout='45s' (schützt Trigram-JOINs vor runaway). (0.2) briefing_auto_analyst.py: 4× psycopg2.connect(**DB_CONFIG) durch Fallback-Pattern mit f-string-DSN-Konstruktion für db_utils ersetzt. (0.3) Audit SELECT DISTINCT company_domain — career_email_miner + phone_enricher haben bereits try/finally+timeout (aus NP-AO-v5). Cluster-Status: W1=26, W2=10, W3=15, W5=14 Daemons, W4 Load 6.3, Backend 200.
AP2 Phase 3-6 — Batch-Migration 148 Scripts 15.04. (Abend)
Nach Phase 1+2 (12 Scripts) restliche ~50 Scripts aus Advertsdata/Spider/Monitoring/Utility-Bereichen via Python-Regex-Batch migriert. Pattern: import psycopg2 + fehlendes from db_utils import → Fallback-Block einfügen. psycopg2.connect(DB|DB_DSN|DB_URL|DSN|dsn|DATABASE_URL|PG_DSN|PG_URL)(_dbutils_connect(X) if _dbutils_connect else psycopg2.connect(X)). AST-parse vor Write verhindert Broken-Code. 168/235 Scripts (71%) mit db_utils. Deploy auf alle 5 Worker via deploy.sh ✅. 67 Scripts nicht automatisch migriert (dict-Config wie `psycopg2.connect(**DB_CONFIG)` oder exotische Import-Forms) — Original-Code unverändert, null Regression-Risiko. Backend 200 in 2ms.
AP2 Phase 1+2 — Connection-Standardisierung 15.04. (Abend)
63/70 Scripts nutzten raw psycopg2.connect() ohne TCP-Keepalives → strukturelle Connection-Leak-Quelle. Phase 1 (6 Daemons: ats_crawler, career_page, vp_matcher, aoe_executor, briefing_auto_analyst, apollo_enricher) + Phase 2 (4 Enricher: contact_completer, career_email_miner, phone_enricher, ats_email_enricher) migriert. Pattern: from db_utils import connect as _dbutils_connect + (_dbutils_connect(DB) if _dbutils_connect else psycopg2.connect(DB)) mit Fallback. scripts/deploy.sh neu — einheitliches Rsync auf alle 5 Worker inkl. db_utils.py. 12/12 kritische Scripts haben db_utils ✅. W4 Load 6.11 stabil. Lektion #66. Phase 3-6 (~50 Scripts: Advertsdata/Spider/Monitoring) folgt. Commit 4aca747.
NP-AO-v7 — W4 CPU-Notbremse + Matcher-Drosselung 15.04. (Abend)
W4 CPU stundenlang >90% durch VP-Matcher Trigram-JOINs. Teufelskreis: Matcher-Last → MV-Refresh timeout → Monitor 0 → Fix-Versuche → mehr Last. Phase 1: Matcher gestoppt. Phase 2: Tag-Config drosseln (firm_chunk 500→100, sleep_batch 0.3→2.0s, sleep_empty 30→60s), Nacht+Übergang eigene Configs. Phase 3: safe_mv_refresh.sh mit SSH-Load-Check (skip wenn W4 >10), Cron `4-59/10` ersetzt. Phase 4: ats_email_enricher conn.commit() nach get_batch() vor async HTTP (schließt Transaction, kein idle-in-txn mehr). Matcher PID 1498743 neu. Final 6/6: W4 12.5 sinkend, JB=887k/ATS=343k, Offline=0, idle-in-tx=0. Lektionen #63 (firm_chunk tageszeit) + #64 (MV Load-Check) + #65 (commit() vor async). Commit 3b2d005.
NP-AO-v6 — FINAL STABILIZE: MV CONCURRENTLY-Bug 15.04. (Abend)
Monitor zeigte 0 für Jobbörsen/ATS/Career trotz 1.13M AD-Jobs. Diagnose: mv_source_buckets war seit 14:10 stale (7h!). Ursache: Cron REFRESH MATERIALIZED VIEW CONCURRENTLY erforderte UNIQUE INDEX — MV hatte nur expr_idx → silent-fail bei jedem Cron-Run. Fix: CONCURRENTLY aus Cron entfernt (1-Row-MV, Lock-Dauer marginal). Manueller REFRESH → jobboersen=882k / ATS=342k / career=68k. W5: 14 Daemons verifiziert (Monitor-UI zeigte fälschlich 1). W2 career_email_miner läuft. Backend 200 in 2ms, Offline=0, idle-in-tx=4 (transient). Lektionen #61 (CONCURRENTLY ohne UNIQUE INDEX = silent-fail) + #62 (ps aux nach Daemon-Start). Commit folgt.
NP-AO-v5 — MEGA-Cleanup Enricher Connection-Safety 15.04. (Abend)
idle-in-tx war zurück trotz NP-AO-v4 — weil nur domain_email_booster gefixt war, andere Enricher (contact_completer, ats_email_enricher, career_email_miner, phone_enricher, domain_resolver) hatten gleiches Leak. Fix: ALLE 6 Enricher mit try/finally + SET statement_timeout='30s'. Plus: rsync --include='*.sh' + chmod +x auf alle 5 Worker (W3 hatte .sh-Scripts noch nicht). Audit: grep -c "finally:" aller Enricher → ALLE ✅. Worker-Daemons gekillt → daemon_keeper Restart mit neuem Code. W5 11 Python-Daemons laufen. Backend HTTP 200 in 7ms. Lektionen #59 (statement_timeout Pflicht in Enrichern) + #60 (rsync *.py+*.sh). Commits cea7ab0 + 693adf8.
NP-AO-v4 — Backend 502 durch idle-in-transaction 15.04. (Abend)
HTTP 502 durch PgBouncer-Pool-Erschöpfung: 5× idle in transaction von domain_email_booster Partitionen (4× 2-5min alt). Root Cause: get_domains()/save_emails() öffneten Connections ohne try/finally — Crash zwischen execute/close → Connection bleibt idle in transaction. Fix: (3) try/finally um beide Funktionen + SET statement_timeout='30s'. (6) Global ALTER DATABASE vakanzpuls SET statement_timeout='120s'. (1+2) Backend-Restart + 4× pg_terminate_backend auf Master+W4. (5) Master description_daemon war sauber (kein Dup). Worker-Booster gekillt → daemon_keeper restart mit try/finally-Code. Lektionen #57 (try/finally Pflicht) + #58 (statement_timeout 3 Ebenen). Commit 2d36379.
NP-AO-v3 — Worker-Deploy + W1 Dedup + Aktiver Duplikat-Kill 15.04. (Abend)
NP-AO-v2 Commits waren korrekt, aber Worker ohne git-Repo hatten neue Partition-Scripts nicht → W3 "No such file"-Loop. Fix 1: rsync scripts/ auf alle 5 Worker (partition-scripts komplett synchron). Fix 2: W1 Duplikate manuell gekillt (ats_crawler 3→1, shadow_monitor 3→1, quality_score_v2 2→1, ältestes PID behalten). Fix 4: daemon_keeper Duplikat-Detection jetzt AKTIV KILL statt nur melden — Pattern pgrep -af PATTERN | sort -n | tail -n +2 | xargs kill -15. Briefing-Endpoint-Timeout bleibt: W4 DB-Load (MV-Refreshes), Monitor-Endpoint läuft (7ms). Lektionen #55 (rsync nach push) + #56 (Kill statt Melden). Commit 71f0431.
NP-AO-v2 — Telegram-Spam Notfall + Auto-Healer-Interferenz 15.04. (Abend)
Drei Systeme (daemon_keeper, auto_healer, briefing_auto_analyst) kämpften um dieselben Daemons, erzeugten Endlos-Alerts. Fixes: (1) briefing_auto_analyst._check_email_rate_stagnation startet keinen email_booster mehr auf Master — Ghost-Kollision mit Worker-Partition-Management. Nur noch Warnung. (2) pkill domain_email_booster.py auf Master, Worker-Partitionen laufen weiter. (3) auto_healer log_max_age: TIS 10→30, Analyst 60→120, Heartbeat 10→20 (Batch-Jobs sind idle zwischen Runs). (4) critical_alert.py:588 filtert real_healer_actions (nur FEHLGESCHLAGEN/down/CRITICAL) vor Send. (5) daemon_keeper Exponential-Backoff: ≥5 Misses → Cooldown 10min→1h. W5 venv verifiziert OK. Lektionen #51-#54. Commit 273f140.
NP-AO — Telegram False-Positive-Audit 15.04. (Abend)
14 benutzte categories waren NICHT in NOTIFICATION_CONFIG → kein Throttle, nur 5min-Dedup (Spam-Risiko). Fixes: (a) NOTIFICATION_CONFIG +14 Einträge (daemon_keeper, daemon_keeper_critical instant, behoerden/hochschulen/gvp_enricher/hr_*, iproyal_quota*, mv_health*, load_throttler, quality_milestone, spider_digest, desc_milestone). (b) crawl_pinpoint.py category="spider_error" ergänzt. (c) critical_alert.py WORKER_DAEMONS komplett synchronisiert mit daemon_keeper EXPECTED: W2 CareerHTML entfernt (nach W3 migriert, erzeugte permanente False-Alerts), +W5 7 Daemons, +W6 2. (d) ATS-Output-Warnings nur Mo-Fr (now.weekday()<5). (e) Spider-Stale-Threshold für Batch-Crawls 3d→7d. Final-Audit: 0 missing categories. Lektion #49 (send_alert MUSS category) + #50 (4-Stellen-Sync für Daemons). Commit 743ddc6.
NP-AN — source_breakdown Null-Schutz + Timeout 2s→5s 15.04. (Abend)
Nach NP-AM Redis-Flush zeigte Monitor Jobbörsen=0/ATS=0 obwohl 1.13M AD-Jobs korrekt. Ursache: mv_source_buckets Query mit 2s statement_timeout crashed unter DB-Last → source_breakdown={} ging in 30min Stale-Cache (verletzt Lektion #20). Fix: (a) statement_timeout 2s→5s für MV-Reads (vorberechnet, darf länger), (b) Stale-Cache-Write nur wenn bool(data.source_breakdown) — leere Dicts gehen NIE in Stale. Fresh-Cache akzeptiert weiter leere Dicts (20s TTL). Verify: 17 keys, jobboersen=882k, ats=342k, ad=1.13M, meta.version 1.2. Lektion #48: Nach Redis-Flush IMMER MV-Refresh + Cache-Warmup-Checkliste. Commit ae10774.
NP-AM — Notfall: Monitor-Dict leer + W2 Daemon-Duplikate + Telegram-Dedup 15.04. (Abend)
Monitor zeigte source_breakdown={}, 4 Daemons offline. Diagnose: W2 hatte 5× contact_completer (statt 2), data_propagator komplett tot, PgBouncer query_wait_timeout durch DB-Überlast. Fix: (1) W2 alle contact_completer killed + clean P0+P1 Wrapper-Restart, (2) data_propagator manuell gestartet, (3) Redis flush + Backend-Restart. Plus Phase 4: telegram_utils._msg_fingerprint() normalisiert jetzt _p0.sh/_p1.sh/..._pX.sh, partition=0/4partition=X, P0/4PX/X. Dadurch 4 Partitionen desselben Daemons = 1 Alert statt 4 (Telegram-Spam-Fix). Final: Offline=0, Jobs=2.5M, Jobbörsen=882k, ATS=342k, AD=1.13M ✅. Commit a07a7ef.
NP-AL-2 — I/O inline + AD Scraper 50→75 15.04. (Abend)
Fix 1: I/O-Wert direkt in die Metrics-Row (Disk | Load | I/O) als smi-Item statt als separatem Badge unter der Karte — garantiert sichtbar. Tooltip mit ↓rx ↑tx MB/s, Farbe nach Durchsatz (grün >10, cyan >1). Fix 2: AD-Scraper Cron --limit 50→75, scraper Code-Default 50→75, iproyal_budget_watchdog CAP_PCT 90→95. Budget-Prognose: 75×4/h×24h×200KB×8× = 9.2 GB/Monat = 92% von 10 GB Plan. Commit 6716adc.
NP-AL-1 — venv-Auto-Detect + triple_enricher 30× + GMaps 10→13 15.04. (Abend)
Fix 1: Alle 24 Wrapper-Scripts regeneriert mit venv-Auto-Detect [ -f venv/bin/python3 ] && PYTHON=venv/bin/python3 — W5 nutzt venv (andere Worker system-python). Plus: phonenumbers pip auf W5-venv nachinstalliert (phone_enricher crash war ModuleNotFoundError). Fix 2: triple_enricher_daemon.py PAUSE_BETWEEN 120→30s, PAUSE_IDLE 3600→120s (4× busy, 30× idle schneller). Fix 3: GMaps WORKER_COUNT 10→13 an allen 3 Stellen (gmaps_turbo default, daemon_keeper, W6 @reboot cron). Verifiziert: W5 6 Partition-Daemons + Load 1.23, W6 14 Container + Load fällt 34→15, triple_enricher auf W2+W3 aktiv. Commit f25c0b7.
NP-AK-HOTFIX — Background-Refresh 12s→30s 15.04.
NP-AK hatte _background_refresh Sleep von 120s auf 12s gesetzt. Aber _monitor_full_sync() braucht 3-5s für ~20 DB-Queries. Bei 12s-Intervall startet der nächste Build bevor der alte fertig ist → Queue-Explosion, Backend unresponsive. Fix: 12→30s. Chain final: Frontend-Poll 15s → Redis-Cache 20s → Refresher 30s. HTTP 200 in 8ms verifiziert. Lektion #47: Refresher-Sleep > max(DB-Build×3, Cache-TTL+10). Commit d22b08a.
NP-AK — Monitor Refresh 30s→15s + Backend-Cache 300→20 15.04. (Abend)
Monitor refreshed alle 30s aber Backend cached 300s (5min!) → selbst bei Frontend-Poll 15s bekommt man 5min alte Daten. Fix: Frontend Countdown RF 30→15, backend setex Redis-Cache TTL 300→20, _briefing_cache in-memory 300→20, _background_refresh Sleep 120s→12s, meta.version 1.1→1.2 (sentinel für Verify). Chain: Poll 15s → Cache 20s → Refresher 12s = Daten nie älter als ~12s. Commit bad4294.
NP-AJ — 4-Partition Scale-Up + I/O-Badge prominent 15.04. (Abend)
W1 bei 4% CPU, W5 bei 5% trotz NP-AI-1. Lösung: TOTAL_PARTITIONS 2→4 für 6 Scripts. 24 Wrapper-Scripts (6×P0-P3) + daemon_keeper umverteilt: W1 +5 (CC/Booster/Resolver/CEM P2), W5 +8 (Phone P2+P3, CC P3, ATS-Email P2+P3, Booster P3, Resolver P0, CEM P0). Partitionen auf 4 Worker verteilt. I/O-Badge: font-size 9px→11px, font-weight 700, ⚡-Emoji, eigene Zeile mit flex-wrap. Verifiziert: W1 Load 0.5→3.86, W5 Load 0.10→1.16, W2 7 / W3 5 / W5 7 partition-daemons. Commit 4bb8fa8.
NP-AI-2 — I/O-Monitoring pro Server + data_propagator DSN-Fix 15.04.
Teil A: data_propagator.py hardcoded 127.0.0.1 → env-aware (Master-Detection + VP_DB_HOST Override). War auf W2 gecrashed.
Teil B: Netzwerk-I/O pro Server. Schema ALTER TABLE server_metrics ADD net_rx_mbps/net_tx_mbps. system_metrics_collector.py mit psutil.net_io_counters() + State-File pro Server für MB/s-Delta (Filter: kein lo/docker0/veth*/br*). Backend-Query + servers-dict erweitert. Frontend: neuer I/O-Badge pro Server-Kachel (grün >10 MB/s, cyan >1, grau sonst) mit RX/TX im Tooltip. Live: Master 1.69/1.64, W2 3.69/0.11, W3 3.49/0.15 MB/s. Commit 52ea430.
NP-AI-1 — Partition-Parallelität: phone_enricher + domain_email_booster P0+P1 15.04.
I/O-bound Daemons bringen Server nicht über 1-9% CPU. Lösung: Partition-Support via env-vars PARTITION_ID/TOTAL_PARTITIONS + abs(hashtext(company_domain))%2=PID Clause. Für 2 Scripts implementiert: phone_enricher und domain_email_booster. 4 Wrapper-Scripts (phone_enricher_p0.sh, _p1.sh + dito booster), daemon_keeper W1 + W3 startet jetzt jeweils 2 Instanzen. Wrapper-Pattern statt env-var-direkt damit pgrep sie unterscheiden kann. Follow-Up NP-AI-2: career_email_miner + domain_resolver + ats_email_enricher. Commit 12c4c29.
NP-AH-3 — Quellen-Nutzung: ATS-Limits hoch, Discovery-Sleeps runter 15.04. (Nachmittag)
Bei 235k Quellen waren ATS-Crawler LIMITs (200-300/Cycle) viel zu klein (0.08% pro Lauf). Fixes: (1) ats_crawler_daemon.py alle 6 ATS-Typen (personio, greenhouse, lever, join, breezy, pinpoint) LIMIT auf 500. (2) ats_slug_discovery.py SLEEP_IDLE 3600→300s (1h→5min). Diagnose: 0 reaktivierbare ATS-Sources mit health≥80+DACH (bereits alle wichtigen aktiv), BA-Backlog=0 (clean), Adzuna 86.6% coverage OK. Nichts weiter zu reaktivieren. Commit 9f48023.
NP-AH-2 — 10 Scripts Throughput-Boost 15.04. (Nachmittag)
Server bei 0-7% CPU mit wachsenden Backlogs → Configs zu konservativ. Hebel: data_propagator INTERVAL 900→120s, career_email_miner 600→120s, description_daemon EMPTY_SLEEP 150→60s, ba_api_fetcher 300→60s, pdf_extractor CONCURRENT 10→20 + IDLE 600→120s, domain_resolver CONCURRENT 20→50, phone_enricher 40→80 (Ziel phone_pct 75%), gmaps_ats_fingerprinter CONCURRENT 20→60 + BATCH 400 + SLEEPs drastisch runter, description_enricher THREADS 3→8, gmaps_daemon QUEUE_EMPTY 1800→300s. Auf 5 Worker deployed + pkill für daemon_keeper-Restart. Commit 5e43b79.
NP-AH-1 — W4 DB-Last: MV-Refresh gestaffelt + Matcher SET-based 15.04. (Nachmittag)
W4 CPU 79-100% Spikes durch gleichzeitige MV-Refreshes auf Minute :00. Fixes: (1) 12 MV-Refresh-Crons auf alle 60 Minuten-Slots verteilt (max 1 REFRESH/min), Einträge wie 1-59/3, 2-59/5, 7,22,37,52. (2) VP-Matcher stage1_batch von Row-by-Row (N Trigram-Queries) auf SET-basiert (TEMP-Tabelle + JOIN, 1× GIN-Scan). (3) DB-Load-Check smarter: nur pausieren wenn REFRESH MATERIALIZED aktiv (echter Blocker), nicht bei generischem state=active. Lektion #46. Commit 327852d.
NP-AG — Frontend-Sync, W5 sichtbar, Shard-Normalisierung 15.04. (Nachmittag)
Dritte Stelle mit altem HIBERNATED-Pattern: monitor/index.html DG hatte tote Aliase (orchestrator, celery) und fehlende W5-Gruppe. Fixes: (1) backend/app/main.py Shard-Normalisierung — Heartbeat meldet description_daemon.py --shard N einzeln, Monitor aggregiert zu einem description_daemon. (2) ALL_DAEMONS um description_daemon erweitert, career_html_extractor W2→W3 korrigiert. (3) DG komplett umgebaut: W5-Gruppe (unsichtbar!) hinzu, Shard-Daemons auf Master/W1/W3/W5. (4) SRVS nd-Counts: M:9, W1:7, W2:6, W3:6, W5:1, W6:2. Ergebnis: 26/26 online, 0 offline ✅. Lektion #45: Daemon-Status wird an 3 Stellen definiert (keeper+main.py+monitor.html) — alle synchron halten. Commit 8fffa43.
NP-AF — VOLLLAST Pipeline-Throughput 15.04. (Mittag)
Cluster bei 1-21% CPU trotz 324k+837k Backlogs → Configs zu konservativ. Fixes: (1) VP-Matcher Tag-Config firm_chunk 200→500, sleep_empty 120→30s, DB-threshold 15→30 → 5× Throughput. (2) Contact-Completer BATCH 300→500, INTERVAL 600s→60s → 10× Throughput, Backlog-ETA 7.5d→11h. (3) PDF-Extractor Tag-Lauf 14:00 MAX_BATCHES=5 zusätzlich zu Nacht (budget-safe 10 GB/Monat). (4) Monitor ALL_DAEMONS Cleanup: 3 tote Aliase entfernt (master_orchestrator, celery, description_daemon) → Offline: 0. Lektion #44: Load ≤20% + wachsende Backlogs = Config-Problem. Commit 00420c7.
NP-AE — Monitor-Backend 3 Bugs gefixt 15.04. (Mittag)
Bug 1: main.py:1758 career_email_miner backlog war hardcoded 0 (Kommentar "DISTINCT query below" aber nie implementiert) → Live-Query mit 15s Timeout, 15.731 Domains. Bug 2: admin_api.py:3494 HIBERNATED_PATTERNS enthielt ats_email_enricher + domain_email_booster trotz NP-Y Reaktivierung → leeres Set, "2 hiberniert" Badge weg. Bug 3: monitor/full hatte keinen fetchers.adzuna_npd Key (nur briefing) → neuer Block mit source IN ('Adzuna','adzuna_at','adzuna_ch','adzuna_de') statt ILIKE für Index-Nutzung → 161.485 Jobs, 86.6% coverage. Bug 4/5/6 waren Backend-seitig korrekt. Lektionen #38-#40. Commit 002230c.
NP-AD — Pipeline-Vollaudit 9 Probleme 15.04. (Mittag)
Monitor zeigte 9 "Stalled" Pipelines. Diagnose: Alle 9 Daemons laufen ✅, die Monitor-Anzeigen sind Reporting-Bugs: (1) VP-Matcher Daemon aktiv aber echtes Throughput-Problem (837k match_status=pending, Cycle findet 4-284 matches → ETA 12+ Tage, Parkplatz #63 NP-AE), (2) Adzuna Cron 04:00+05:00 läuft, 703 matched heute trotz Monitor "0%/24h", (3) Career-Email-Miner W2 aktiv (51k Queue), (4) TMG Master aktiv (hr_companies 8.851→9.520 email, +669/2.5h), (5) PDF by-design 1×/Tag nachts (NP-AC), (6) W5 alle 3 Shards laufen (Hash-Verteilung-idle), (7) W6 Swap 6.7 GB Legacy (46 GB RAM available, kein Druck), (8) "2 hiberniert" Badge = UI-Artefakt, (9) Contact Completer W2 läuft (11k pending, nicht 323k). Parkplatz #63-65 dokumentiert für Follow-Up.
NP-AC — Full-Stabilisierung 7 Phasen 15.04. (Mittag)
Systematic harden: (1) Code-Defaults safe: pdf_extractor MAX_BATCHES 0→10, proxy_scraper --limit 500→50. (2) Telegram category= ergänzt in crawl_breezy, crawl_icims, pipeline_wakeup_checker. (3) heartbeat_sender.EXPECTED_DAEMONS 1:1 zu daemon_keeper (worker-5 hinzu, präzise Shard-Pattern). (4) daemon_keeper Duplikat-Detection: python-only count (bash-wrapper excluded). (5) db_utils.py selbst env-aware — Master-Detection via hostname, VP_DB_HOST Override, Fallback 161.97.79.192. Behebt stillen W3 domain_email_booster Bug. Lektionen #34-#37. Commit 7dcd7fa.
NP-AB — W1 Load 324 Notfall + systemd-Unit Root Cause 15.04. (Mittag)
NP-AA Phase 1 hatte W1 Load 324 🔴 detektiert. Root Cause: gmaps-daemon.service SYSTEMD auf W1 aktiv (NP-W hatte nur pkill gemacht, systemd-Unit übersehen) → respawn-loop spawned 25 Docker-Container + 502 Chrome. Fix: sudo systemctl stop+disable gmaps-daemon.service + docker kill/rm all + pkill chrome. Load 307→63 in 3 min. Zusätzlich: W5 description_daemon Shard 7 doppelt, jüngere PID 3746574 killed. W6 Load 64 verifiziert OK (10 Container, turbo env GMAPS_WORKER_COUNT=10). Parkplatz #58/#59/#60 ✅. Lektion #33: GMaps-Respawn-Quellen sind DREI (cron + systemd + docker-restart-policy), nicht nur eine.
NP-AA — DSN-Hardening + Parkplatz-Cleanup 15.04. (Mittag)
6 Phasen-Prompt: Phase 1 Health-Check, Phase 2-5 Fixes, Phase 6 Doku. Fixes: (1) domain_email_booster env-aware DSN + db_utils-Fallback (#56 ✅), (2) idle_txn_killer um active>60min-Kill erweitert + pg_idle_txn_killer deaktiviert (#46 ✅), (3) phone_enricher Symlink scripts/phone_enricher.py → enrichment/ auf Master+W1 (#51 ✅), (4) 5 Worker-Scripts DSN+TCP-keepalives: ats_email_enricher, career_html_extractor, domain_resolver, quality_score_v2, ats_crawler_daemon. Alle auf 4 Worker rsynced. Phase 1 Auffälligkeiten: W1 Load 324 🔴 (#58 NP-AB dringend), W5 Shard 7 doppelt (#59), W6 Load 64 (#60). Lektion #32. Commit 96e7459.
NP-Z — W6 Load 296 Notfall, GMaps Worker-Count permanent gefixt 15.04. (Mittag)
Nach NP-X (Load 1.33) explodierte W6 wieder auf Load 296 mit 25 Containern. Root Cause (3 Stellen out-of-sync): (a) gmaps_turbo.py Code-Default 25, (b) daemon_keeper Restart-Command ohne env, (c) W6 lokal docker_watchdog */3 (W2-Pattern geerbt), (d) @reboot Cron ohne env. Fixes: Code-Default 25→10 (Commit 559710a), daemon_keeper restart-command mit GMAPS_WORKER_COUNT=10 (Commit 3aa5d18), docker_watchdog auf W6 DISABLED, @reboot-Cron mit explicit env. Load 296→21.77 in 2min, 25 Container→0. Lektion #31: GMaps Worker-Count an 3 Stellen sync halten.
NP-Y — Queue-Refill + Hibernation-Wake + TMG-Revive + AD-Range dynamisch 15.04. (Mittag)
Cluster war idle weil 5 Discovery-Crons seit 09.04 auskommentiert, 2 Pipelines HIBERNATED, TMG seit 12.04 tot, advertsdata-Range hardcoded exhausted. Fixes: (1) 5 Discovery-Crons reaktiviert (gmaps_ats_fingerprinter, ats_slug_discovery, api_maximizer, gmaps_validator, discover_ats_tenants), (2) HIBERNATED geleert, ats_email_enricher+domain_email_booster auf W3 live + daemon_keeper EXPECTED erweitert, (3) TMG §5 Email-Extractor reaktiviert (hr_companies 8.851→8.974 in 20min, 100k pending, Cron-Watchdog */5), (4) advertsdata_watchdog restarts/actions Init-Bug (NameError 1. Restart), (5) advertsdata_proxy_scraper Range dynamisch via MIN/MAX+50M Puffer. Lektion #30: Zufluss-Pipelines niemals dauerhaft auskommentieren. Commit d24dcb3.
NP-X — Cluster-Rebalance Marathon (W2-Watchdog-Loop, W6-Throttle, ATS-Revert) 15.04.
W2 98% CPU Root Cause: lokale Crontab hatte docker_watchdog */3 + worker_watchdog */10 aktiv (NP-F hatte nur Master-Cron deaktiviert). docker_watchdog respawn'd alle 3min die NP-W-gekillten gmaps-Container = Endlos-Loop. Fixes: career_html_extractor W2→W3 migriert (daemon_keeper EXPECTED), W2 lokale Watchdogs auskommentiert, W6 GMAPS_WORKER_COUNT=10 (default 25 = Load 314, jetzt Load 1.33). ATS-Revert NP-V Init 4: 18/20 reactivated waren US-Sources (Auto-Deactivated Non-DACH, health=30, Filter-Bug `=100` matched AVG nicht Einzel). Final-Loads: M 2.45 / W1 0.23 / W2 0.86 / W3 0.08 / W5 0.09 / W6 1.33 — alle <80% ✅. Pipeline OK: phone_pct 23.71→28.24% (+4.5 Pkt/h), 880 Jobs/30min, 134k GMaps done. Lektionen #27-29. Commit fdb615a.
NP-U/V/W — Budget-Notfall, Phone-Fix, Cluster-Rebalance 15.04. (Vormittag)
NP-U: proxy_scraper --limit 500→50 (1.9 GB/Tag → 192 MB/Tag). NP-V Init 1 Phone-Enricher best_score≥0 (Parkplatz #50 ✅, phone_pct 23.71→26.71% in 25min) + Init 2 +25 GMaps-Keywords (Handwerk/Pflege/Gastro, +1.145 Queries) + Init 3 NX-GM-P1 Sandro-GO aktiviert (Activator --min-hit-rate 0 + results_count Backfill) + Init 4 ATS-Audit (208 Sources mit reason=NULL, Sandro-Entscheid). NP-W: W1 Load 318→0.62 Faktor 510× (25 gmaps-worker-Container + 525 Chrome + 42 GB Chromium-RAM liefen fälschlich auf W1), Master gvp-Zombie 7d@99.8% gekillt, phone_enricher+salary_extractor W1/W3/W5 synced. Lektionen #25 (load-avg 100+ erst docker+chrome prüfen) + #26 (Ghost-Files Master/Worker). Commit 41009e1.
NP-AH–AO — Pipeline-Stabilisierung Marathon 15.04. (Nachmittag/Abend)
NP-AH-1 W4 DB-Last: 12 MV-Refresh-Crons gestaffelt, VP-Matcher stage1 SET-basiert (TEMP+JOIN statt Row-by-Row), DB-Load-Check smarter. NP-AH-2 10 Scripts Throughput: data_prop/career_miner/desc/ba_api Sleeps runter, CONCURRENT hoch (pdf 20, domain 50, phone 80, gmaps_fp 60), gmaps_daemon QUEUE_EMPTY 1800→300s. NP-AH-3 ATS-Crawler LIMIT 200-300→500 (6 Typen). NP-AI-1+2 Partition-Parallelität (phone_enricher+domain_email_booster via hashtext%2, 4 Wrapper-Scripts) + I/O-Monitoring (psutil MB/s in server_metrics +net_rx/tx_mbps). NP-AJ 4-Partition Scale-Up (TOTAL_PARTITIONS 2→4 für 6 Enricher, 24 Wrapper, W1 +5/W5 +8 Daemons). NP-AK+HOTFIX Monitor Refresh 30s→15s + Backend TTL 300→20s + Refresher 12s (war zu aggressiv, auf 30s korrigiert). NP-AL-1+2 venv-Auto-Detect in 24 Wrappers (W5 nutzt venv), I/O inline im Monitor, AD Scraper --limit 50→75. NP-AM Notfall: W2 contact_completer 5× Dup, data_propagator offline, source_breakdown={}. Telegram Partition-Dedup (_p0/_p1 → _pX). NP-AN Monitor source_breakdown Stale-Cache-Guard. NP-AO bis v7b Telegram False-Positive-Audit (14 Categories ergänzt), Backend 502 durch idle-in-tx (try/finally + statement_timeout 30s in 6 Enrichern), MV mv_source_buckets CONCURRENTLY silent-fail, W4 CPU-Notbremse (Matcher Tag 500→100, safe_mv_refresh.sh Load-Check), career_email_miner+contact_completer conn.commit() nach fetchall. Commits cea7ab0 + 2d36379 + 71f0431 + 273f140 + 743ddc6 + ae10774 + a07a7ef + 6716adc + f25c0b7 + d22b08a + bad4294 + 4bb8fa8 + 327852d + 5e43b79 + 9f48023 + 12c4c29 + 52ea430. Lektionen #30-#67.
AP2+AP3+AP4 — Connection-Standardisierung + Email-Boost + Observability-Layer 15.-16.04.
AP2 Phase 1-6 (Commits 4aca747+): 168/235 Scripts auf db_utils.connect() migriert (TCP-Keepalives + reconnect_on_drop). Batch-Regex-Pattern mit Fallback-safe Original-Code. scripts/deploy.sh für einheitliches Rsync auf 5 Worker. AP3 Phase 0 (15.04 23:15): advertsdata_vp_matcher_daemon statement_timeout 45s für Trigram-JOINs, briefing_auto_analyst DB_CONFIG → db_utils-Fallback. AP3 Phase 1 Email-Boost (16.04, Commit 8dd673e): BATCH_SIZE 2× (domain_email_booster, career_email_miner) + 2.5× (ats_email_enricher). rsync 5 Worker. Wirkung: emails/10min 150→3188 (21× Durchsatz). ETA 80% Ziel: 23 Tage → 11h. AP4 Meta-Layer (Commit afbe610+a39b4ce): 5 Phasen Observability. DB-Schemas: pipeline_metrics_hourly, telegram_audit, iproyal_budget_history. 4 Collector-Crons auf W2: pipeline_metrics_collector (hourly), daemon_code_freshness (*/15), deploy_drift_audit (*/4h), iproyal_dashboard_scraper (*/15). 3 neue API-Endpoints /api/monitor/{trends,iproyal,telegram-audit}. Erste Runs fanden 4 stale Daemons + 5 Worker-Drift + telegram_audit-Hook live.
Shadowfix-Full + UPSERT + NP-P1/P2/P3 + SHF-ADVERT 16.04. (Mittag)
7 Shadowfix-Prompts abgearbeitet (Commit 49a310c): p15 KERN-FIX PgBouncer default_pool_size 40→80 (Pin #95 Root-Cause), server_idle_timeout 600→1800. p16 monitor_health_alert.check_idle_txn auf ResilientConn. p05 breezy/pinpoint/jazzhr/bamboohr Smoke-Tests OK. p03 Bandwidth-Counter reset, PROXY_OVERHEAD_FACTOR=3.5. p09 awo/caritas-Deaktivierung ist kein Bug (DNS-fail der Zentralbörsen). p28 gmaps_daemon QUERIES_PER_RUN 20000→3000 + timeout 4h→1h + Queue-Reset bei TimeoutExpired. p27 Baseline. Plus UPSERT-Batch-Fix (Commit 7bb0034): 27 Files gefixt (alle ATS-Core-Spider, ON CONFLICT DO UPDATE SET crawled_at=NOW()). NP-P1 BA-API Backlog 99.98% schon weg. NP-P3 Arbeitnow Public API, 1.051 Jobs (Commit e8e23a6). NP-P2 EURES Skeleton (API blocked, Commit bb0be2c). SHF-ADVERT PDF-Extractor Daemon-Mode auf W3 (Commit e46fab2). SHF-ATS icims+dvinci ResilientConn (Commit df932b8). SHF-P03v3 IPRoyal PID-Lock + Cron-Konsolidierung (Commit c81a65a). Lektionen #68-#80.
AP4-COMPLETION — IPRoyal-Tile-Fix + Monitor v6.7 + LLM-Classifier 16.04. (Abend)
IPRoyal-Tile-Fix (main.py _read_iproyal_quota): state-file UNDERESTIMATES real usage, Korrekturfaktor STATE→REAL=1.38× (nicht 2.16×/divisiv wie zunächst angenommen). Tier-1-Quelle bleibt iproyal_budget_history dashboard-source. Monitor v6.7: 3 neue Tiles (Grid-Row 4, 30s Refresh): Pipeline Trends 48h (4 Sparklines), IPRoyal Burn-Rate 7d (SVG-Chart + Forecast), Audit Summary 48h (Top-Categories). LLM-Classifier scripts/telegram_audit_classifier.py: Claude-Haiku-API, Cron 0 */4 auf W2, 12 Alerts klassifiziert (5 INFO/4 FALSE_POSITIVE/2 ACTION_REQUIRED/1 INFO). Quad-Sync scripts/daemon_config_sync_check.py: 4-Way-Drift keeper↔heartbeat↔main.py↔critical_alert, Cron */30 W2. Heartbeat-Completeness scripts/heartbeat_completeness_check.py: Cron */15 W2. NOTIFICATION_CONFIG +6 Categories. Lektionen #81-#87 (Bandwidth-Faktor 8→1.38 Doppel-Bug resolved).
Shadowfix p05/p15/p03/p09/p16/p28/p27 v2 + BUDGET-EMERGENCY 17.04. (Mittag)
Re-Verifikationen der Shadowfix-Prompts: p15 v2 (Commit d87e5b9): Pre-p15 19.847 query_wait_timeout/45min → Post 0 in 45min clean. p03 v2 (Commit c5fad17): Cron --limit 75→25, IPRoyal-State auf Ground-Truth korrigiert, Overhead-Faktor 2.16× empirisch. p05 v2 (Commit 2e5a2a3): 0 Tracebacks/DB-drops über 4 Spider-Smoke-Tests. p09 v2 (Commit 451e344): awo/caritas 97.91% aktiv (888/907). p16 v2 (Commit 4468bfb): Monitor mit ResilientConn, 5× Smoke grean, 0 KRITISCH in 30min. p27 v2 (Commit a335f14): ats_crawler_daemon 40h stuck — join/breezy/pinpoint Spider fehlten auf W1 in gemeinsamem try-Block, rsync+restart. p28 v2 (Commit fde1746): GMaps-Daemon pkill + Queue-Reset (14.800 stuck→pending). BUDGET-EMERGENCY (Commit 7655d2f): IPRoyal 5.02→4.55 GB in 20min, PDF-Extractor Doppelstart gestoppt, Proxy 0 */6 --limit 2. Lektionen #71-#78.
GMaps Monitor Fix — Per-Container-Finalisierung + Batch-Größen-Kalibrierung 17.04. (Nachmittag, Commit ffcba51)
Root-Cause: gmaps_turbo.py finalize() markierte ALLE Queries erst nach dem letzten Container als done → done_1h=0 für gesamten Batch (83-167min). Alle 5 Worker (W1/W2/W3/W6/Master) zeigten 0/h im Monitor. Fix 1 (Permanent): Per-Container-Finalisierung: split_and_write() gibt chunk_ids per Split zurück → durch start_workers() propagiert → wait_for_completion() ruft sofort nach Container-Exit import_csv_file() + finalize(chunk_ids) auf. done_1h steigt nun nach 8-17min statt 83-167min. Fix 2: gmaps_daemon.py QUERIES_PER_RUN 3000→600 (600÷4=150/Container @9 Queries/min = 17min, 600÷8=75/Container = 8min). Fix 3: /api/monitor/gmaps-cluster +started_1h-Spalte als sofortiger Aktivitäts-Proxy (wird bei prepare_batch() sofort gesetzt, auch wenn noch kein Container fertig). Monitor zeigt jetzt "~N lfd" (gold) statt "0/h" (rot). 15.200 stuck-running Jobs (aus altem Batch-Run) auf pending zurückgesetzt. W5 erklärt: dedizierter advertsdata-Scraper, NICHT im GMaps-Cluster. Deployed: rsync auf alle 4 Workers (W1/W2/W3/W6), gmaps_turbo pkill, daemon_keeper respawn mit neuem Code. Queue: 110k pending bereit. Lektionen #141 (Batch-Finalize erst nach ALL-Containers = done_1h=0), #142 (Batch-Größe kalibrieren an Container-Finish-Zeit), #143 (started_1h als Aktivitäts-Proxy). Commit ffcba51.
ENRICHER-RECOVERY + PIPELINE-BALANCE + PIPELINE-RELIABILITY + DEEP-DIAG 17.04. (Abend/Spätabend)
ENRICHER-RECOVERY (Commits 3b8c49b+8fe0e86): heartbeat_sender 1:1 zu daemon_keeper (alle _pN.sh einzeln trackbar), Backend-Normalisierung _pN→base (eliminiert "6 offline"-Bug bei phone_enricher/contact_completer etc.), w4_auto_solver Cron */2 (kill idle-tx>60s + max 2 parallele REFRESHes + drossel VP-Matcher bei Load>12). Throughput 259/h→615/h = 2.4×. PIPELINE-BALANCE (Commit 2832eab): Auto-Solver LOAD_THRESHOLD 12→8 (W4 hat 8 vCPUs), Enricher-Whitelist gegen idle-tx-Kill (application_name NOT ILIKE '%enricher%' + query-pattern), Contact-Completer 70/30 Aging-Bias (591k Backlog >7d alt). Aging via ORDER BY crawled_at ASC = Index-Scan 38ms (hashtext-Sampling war 30s+ timeout!). PIPELINE-RELIABILITY (Commit 9916b76): 3 Bugs+2 neue Detection-Layer. ats_crawler except:pass silent-fail (personio 3d/25h down ohne Alert!), W6 daemon_keeper env-loading-Fix (DB_HOST war 127.0.0.1 ohne cd && .env), w4_auto_solver significant-trigger (kein Spam bei 1-2 idle-tx, throttle 1800→3600s). NEU: pipeline_health_alert.py (*/15, 22 Categories per-source last_insert_age), cluster_full_scan.py (0 */2, heartbeat+DB+sources+disk+load). DEEP-DIAG (Commits c36293b+8c2d07c+a7e082f): 12 Spider-Files hardcoded DB_DSN 127.0.0.1 → env-aware via _resolve_db_host_dsn() Pattern. 8 ATS-Spider + 4 crawl-Scripts gefixt. ats_personio LIVE (741 inserts/15min, war 0/3 Tage). ats_teamtailor LIVE (96 inserts/15min, war 0/25h). 24 stuck DB-Connections terminated (4 LISTEN seit 4.2 Tagen!). Lektionen #88-#97.
HANDOFF 18apr_session + Session-Doku 17.04. (22:55)
Selbst-enthaltender Start-Prompt .claude/HANDOFF_18apr_session.md fuer nächste Session. 18 Commits Session dokumentiert, Cluster-Snapshot (jobs_active 1.411.813, enriched 1.385/h, W4 Load 12.70 chronisch, GMaps Queue 0/5000, IPRoyal 7.32/10 GB, 98 UNKNOWN Telegram-Audits). 9 neue Lektionen #88-#97. 5 Top-Follow-ups priorisiert (W4-Load, ats_join 13.6d off, UNKNOWN-Audit-Classifier, CC-Backlog 591k, Email-Pct 65.1%→80%). CLAUDE.md komplett für 17.04-Stand. Commit 01790d4.
Quality Sprint Track A — Score v3 + Validation + Dedupe + Portal-APIs 18.04.
Branch quality-backend, 6 Commits, +2.359 Zeilen: Phase 0 (0c84382): mv_quality_tiers MV (1.41M Rows), validation_results + dedupe_candidates Tables (job_id UUID angepasst), trust_score SMALLINT-Spalte + Partial-Index, MV-Refresh-Cron */10 (statement_timeout 120s). Phase 1 (00a1a88): scripts/quality_score_v3.py (neue Gewichtungen Email25/generic:10, Desc15/10, Domain10, ATS10) + 8 neue Endpoints /api/v1/quality/* (tiers, tiers/history, inspector, inspector/{id}, inspector/export xlsx+csv, inspector/bulk PATCH, validation-stats, dedupe-stats). Redis-shared Cache via app.cache (qa: prefix). Phase 2 (d314221): email_validator_free.py (W2 Daemon, 5 free Checks syntax/MX/not_generic/name_match), dedupe_engine.py (3 Strategien email_exact/firma_domain/titel_ort), gf_name_matcher.py, Trust-Score-Berechnung in v3. Phase 3 (f653c30): gvp_validation.py (8.406 GVP-Emails in 3:26min, 97.8% MX, 58.4% not_generic). Phase 4 (c11cd34): /customer-overview + /trust-score/{id} Endpoints + min_quality/min_trust/exclude_generic Filter auf /jobs/search. Live-Demo-Zahlen: astrein 47.266 (×3 über Prompt-Ziel 15k) / gut 443.681 (×5 über 80k) / Validation 18.805 Emails / Dedupe 217.665 email_exact. trust_score 1.560→10.041. Lektionen #100-#104.
QA Fixes Round 2 18.04. Nacht (Commit f344d75)
Fix 0 CRITICAL Search-Endpoint hing 7.5s: 3 Partial-Indexe CONCURRENTLY auf W4 (idx_jobs_quality_active, idx_jobs_trust_active, idx_jobs_quality_coalesce_active) + filters.py build_order_clause auf COALESCE(col, 0) DESC umgestellt, damit Planner den Expression-Index matcht (vorher "quality_score DESC NULLS LAST" triggerte Bitmap Scan). EXPLAIN 7.491ms → 0.254ms = 29.500× schneller. Plus trust_score als Sort-Key whitelisted. Lektion #132 (Expression-Index-Matching erfordert identische ORDER-BY-Expression). Fix 4 HIGH Sidebar: Datenqualitaet aus INTELLIGENCE (Item 9/11) → MARKT (nach HR-Kontakte, Badge "Neu"). globals.css --sidebar-w 240px→260px + textOverflow:ellipsis entfernt — Personaldienstleister ist voll lesbar. Fix 5: FALSE-ALARM nach Diagnose (Monitor=Briefing=DB exakt, heartbeat_sender Master+W2 aktiv). Lektion #133 (Vor Fix erst Source-of-Truth-Vergleich).
QA Post-Sprint Fixes 18.04. (Commit 26d66bf)
Fix 1 HIGH stellenanzeigen/page.tsx: hardcoded localhost:8003/api/v1/api/v1. stFetch normalisiert Legacy-Paths. FU4: 9 weitere Files frontend-wide gefixt (lib/api.ts, akquise/tagesplanung, pricing, personaldienstleister, firmen, firma, hr-kontakte, hr-kontakte/firma, stellenanzeigen/pdf). Fix 2 HIGH daten-qualitaet/page.tsx: 4 Fetches (overview/checks/customer-overview/history) mit Bearer-Token — vorher silent 401 bei auth-geschuetzten Endpoints. Fix 3 MEDIUM trust_score vollstaendig aufgefuellt: 10.041 → 57.560 Jobs (+47.519, 5.7× Coverage). compute_trust mit 3-Retry+Reconnect gegen PgBouncer-Drops. _build_trust_update_sql: DISTINCT ON(job_id) + JOIN + Diff-Filter IN der Subquery (nicht UPDATE-WHERE — sonst picked LIMIT immer dieselben Rows, Daemon-Loop no progress). Return-Tuple (updated, conn). FU1 placement/page.tsx trust_verified: 10 Factor ergaenzt (Backend-Scorer separater TODO). FU3 Dedupe alle 3 Strategien: email_exact 217.665 + firma_domain +17.437 NEU + titel_ort +35 NEU. Lektionen #127 (Filter in Subquery bei UPDATE+LIMIT) + #128 (Return-Tuple fuer Reconnect-Pattern).
OBER-PRIO W4 + W6 Fix 18.04. (Nacht, Commit 9608fee)
W4: Auto-Solver LOAD_THRESHOLD 8.0 → 13.0 (nproc auf W4 = 12, nicht 8 wie angenommen). Vorher 30 aufeinanderfolgende w4_auto_solver.log-Runs mit matcher_killed=True (Kill/Restart-Loop alle 2min reduzierte VP-Matcher-Durchsatz statt zu verbessern). Nachher: letzte Runs (Load 12.67, 11.56) ohne Matcher-Kill. Lektion #125. W6: gmaps_jobs hatte 5.000 stuck-running (worker-6 seit 19:49, 0 Docker-Container, gmaps_turbo-Log 11h alt in "30min-Pause"). gmaps_queue_refill --check-only Guard (pending<200 AND running<100) blockiert bei 5k-stuck. Fix: UPDATE gmaps_jobs SET status='pending' WHERE status='running' AND started_at < NOW() - INTERVAL '1 hour' + pkill gmaps_turbo (daemon_keeper spawned neu, PID 2558456→2915586). Nachher: 13 gmaps-worker Docker-Container live, pipeline aktiv (pending=2000/running=3000). Lektion #126 (Refill-Guard sollte Zombie-Trigger running>300 AND no_progress_1h bekommen).
CC16 — Quick-Win Alerts GAP-1..GAP-5 (CC_PROMPT 15) 18.04. Abend (Commit df92e81)
5 kritische Alert-Lücken aus Gap-Analyse geschlossen. Alert-Coverage 37/115 → 42/115 = 37% (+5). Alert 1 — KQI-Drop (quality_benchmark.py): check_kqi_alert() nach run_benchmark(). CRIT<78%, FAIL<80%, WARN<82%, TREND>3pp/24h aus kqi_history. Test: prev=83.9%→80.8% → WARNING+TREND korrekt gefeuert. Cron 23:55 (vorhanden). Alert 2+3 — Desc+Dedupe Backlog (pipeline_health_alert.py): check_backlog_alerts() neu. Desc via mv_dashboard_kpis.jobs_active-jobs_mit_description (kein 1.4M-Scan). Dedupe via dedupe_candidates WHERE status=pending. Je WARN>150k/CRIT>250k. Test: 234k desc → WARNING, 235k dedupe → WARNING. Cron */15 (vorhanden). Lektion #163 (MV statt COUNT auf 1.4M Rows). Alert 4 — Spamhaus Check (scripts/spamhaus_check.py NEU): 4 Blacklists (Spamhaus ZEN/SpamCop/Barracuda/SORBS) via dig +short reverse_ip.zone. Test: Master 161.97.79.192 → CSS 127.0.0.3 detected, Alert gesendet. W6 clean. Cron 0 6 * * * neu. Lektion #164 (127.0.0.3=CSS vs 127.0.0.2=SBL). Alert 5 — ACTION_REQUIRED Eskalation (telegram_audit_classifier.py): Am Ende von main(), >50/24h → ESKALATION mit Top-3-Snippets. Test: 448/24h → Eskalation gefeuert. Rsync W2. Cron */2 (vorhanden). Lektion #165 (send_alert category throttle verhindert Spam).
CC15 — Audit-Fixes P0+P1 — 7 Fixes (CC_PROMPT 14) 18.04. Abend (Commits b530b04+c916716)
7 Fixes aus Platform Audit v1.1 + Gap-Analyse abgearbeitet. Fix 1 (P0): W6 crontab GMAPS_WORKER_COUNT=13→8 — Root-Cause Env-Drift war @reboot-Cron (nicht daemon_keeper). Container 13→8 verifiziert. Fix 2 (P1): VACUUM FULL crawler_sources 948 MB → 184 MB (-764 MB). autovacuum_scale_factor=0.01 permanent. Fix 3 (P1): 5 unused Indexes gedroppt: idx_vp_position_trgm(433MB) + idx_jobs_position_fts(326MB) + idx_quality_score(129MB) + idx_quality_grade(129MB) + idx_jobs_processed(44MB) = -1.060 MB. Fix 4+5 (P1): ATS-Crawler Reihenfolge greenhouse+lever VOR personio. personio LIMIT 500→1000, Intervall 12h→8h. Root-Cause war Cycle-Zeit >24h. Fix 6 (P1): heartbeat_sender.py: gmaps_daemon + gmaps_reaktor aus Master-EXPECTED entfernt (Lektion #144-Drift). Eliminiert ~37 false-positive ACTION_REQUIRED/Tag. Fix 7 (P2): .gitignore +gmaps/results/*.csv +turbo_batch_*.txt. 51 → 0 uncommitted files. Lektionen #159-#162.
CC14 — Monitoring-Gap-Analyse 115 Metriken × 5 Säulen (CC_PROMPT 13) 18.04. Abend (Commit 2264e63)
Vollständige Diagnose: 115 Metriken × 5 Säulen (Gemessen/Dashboard/Briefing/Alert/Self-Heal) = 575 Checks. Coverage-Matrix: Gemessen 90% (104/115), Dashboard 74% (85/115), Briefing 57% (66/115), Alert 32% (37/115) — KRITISCH: 78 Metriken ohne Alert, Self-Heal 25% (29/115). Schlimmste Ebene: Qualität (Ebene 4) mit nur 4% Alert-Coverage (1/27 Metriken). Top-10-Gaps (P0): (1) Spamhaus kein Auto-Check (nur manuell via dig), (2) KQI kein Drop-Alert (KQI 80.8% — nur 0.8% über PASS-Schwelle), (3) ACTION_REQUIRED-Eskalation kein Alert (395 unreviewed), (4) Description-Backlog kein Alert (232k ≫ 10k NX-GM-P1-Blocker), (5) Dedupe-Backlog kein Alert (235k), (6) GMaps-Bridge inaktiv kein Alert, (7) HR Name-Coverage kein Alert (36.8%), (8) Grade-S-Drop kein Alert, (9) crawler_sources Bloat kein Alert, (10) KQI-History kein Trend-Alert. Quick-Wins (je <1h): Spamhaus-Cron, KQI-threshold in quality_benchmark.py, Description-Backlog-Check in pipeline_health_alert.py. Report: docs/audits/gap_analysis_2026-04-18.md.
CC13 — Platform Audit v1.1 Vollaudit (CC_PROMPT 12) 18.04. Abend (Commit 4caa836)
Vollständiger 5-Ebenen-14-Domänen-Audit. Score 61/100 🟡 (Erstdurchgang: 75/100 — neue Findings drücken Score). P0 erledigt: W6 13→8 Container, Briefing Redis stale DEL, Lock-TTL 90→120s. Neue Findings: (1) crawler_sources 128.4% Bloat (598k dead / 466k live — Autovacuum überwältigt). (2) 1,676MB Unused Indexes (10 Indexes mit idx_scan=0: idx_vp_position_trgm 433MB, idx_jobs_position_fts 326MB, idx_mv_je_search 294MB, etc.). (3) ATS crawled_24h=0 für greenhouse + lever; personio=10 (kritisch niedrig). (4) 395 Telegram ACTION_REQUIRED unreviewed in 24h (2.289 total, 602 unclassified). (5) HR Name Coverage 36.8% (63k/171k, Ziel >50%). (6) Description Backlog 232.798 (NULL oder <50 Zeichen — NX-GM-P1 bleibt geblockt). (7) Spamhaus CSS 127.0.0.3 bestätigt (Sandro). (8) 8/14 Monitoring-Domänen ohne Alert. Baseline 25.04: Score ≥70, Bloat <20%, unused indexes <100MB, Backlog <50k, Dedupe <150k. Lektionen #155 (dead tuples > build-rate), #156 (unused indexes quarterly audit). Report: docs/audits/platform_audit_2026-04-18.md.
CC12 — Monitor ATS-Kachel Optimierung + Briefing Redis-Fix 18.04. Abend (Commits c895188 + 31ab828)
3 Fixes: (1) Log-Datei: touch logs/batch_ats_discovery.log — Datei fehlte, Cron 30 */2 appendet jetzt. (2) Briefing ATS-Block 24→27 Typen: Redis DB2-Key war seit 15:25 stale (2.5h). Root-Cause: Build-Dauer ~85s bei Lock-TTL 90s => Race-Conditions servten stale Key perpetuell. Fix: redis-cli -n 2 DEL der 3 Briefing-Keys + fresh=1 über localhost:8003. Verify: 27 ATS-Typen inkl. hr4you ✅ talention ✅ coveto ✅ (generated_at=18:13). (3) Monitor ATS-Kachel: CSS 2-col → 3-col Grid (.atsg) → 27 Typen = 9 Reihen ~198px (ragt nicht mehr in benachbarte Rows). Kompakte Items (padding 2px/5px, font-size 9px, text-overflow ellipsis). .ats-idle{opacity:0.35} für Inaktive. JS rATS(): active-first Sort (aktiv_24h>0 zuerst), Header-Badge "N/M aktiv", Info-Line "M Systeme · N aktiv 24h". Lektion #151 (Redis DB-Key-Namespace mit -n 2 prüfen) + #152 (Lock-TTL 90s bei 85s-Build = Stampede-Risiko).
CC11 — ATS-Fingerprinter +3 Patterns + Batch-Discovery 18.04. Abend (Commit b778cf9)
gmaps_ats_fingerprinter.py: 18→21 ATS-Patterns (+hr4you, +talention, +coveto). scripts/batch_ats_discovery.py (NEU): Career-Page HTML-Scan für hr4you/talention/coveto auf 272k Quellen. ThreadPoolExecutor (15 Worker), DB-Connection außerhalb HTTP-Phase (PgBouncer-Timeout-Fix), State-File /tmp/batch_ats_discovery_state.json (resumierbar). Erster Scan (5.500/272k): +6 hr4you, +12 talention, +5 coveto. Gesamt-Quellen: hr4you 10 · talention 13 · coveto 15 = 38 Portale total. Cron 30 */2 auf Master (3000 URLs/Run).
Post-NX-QE Session — P0 W6 + QE-2 Webhook + QS-5 v3 + P3 Briefing 18.04. Nachmittag (Commit b0cc3e9)
P0 W6 Stabilisierung: GMAPS_WORKER_COUNT 13→8 permanent in daemon_keeper.py (W6 line 139). Load 108→24 in 4min. Lektion #150 (gosom ~8 Proz./Container, Threshold = floor(vCPU/2)). QS-3 telegram_audit_classifier: MAX_BATCHES 4→8 (400 alerts/run Kapazität), Cron 0 */4 → 0 */2 auf W2. QE-2 Bulk-Verify Webhook (Commit 6583fb9): quality_engine/api/job_store.py (verify_jobs Tabelle, ensure_table/create/update/complete/fail/get mit auto-expire 1h + set_webhook_status) + job_worker.py (process_bulk_job async background + _fire_webhook HMAC-SHA256 via hmac.new, aiohttp, delays=[0,5,30]s, 10s timeout). GET /verify/job/{id} + /webhook live. httpbin-Test: Delivery Attempt 1 OK. QS-5 quality_score v3 Migration: v2 auf W1 gekilled, daemon_keeper v2→v3 (W1 line 72), heartbeat_sender+critical_alert 4-Way-Sync, score avg 48.8 (Parität v2), v3 aktiv. P3 Briefing-Metriken (Commit b0cc3e9): _get_scheduler_state_safe() liest nicht mehr stale JSON-Datei (4 Tage alt, worker_scheduler.py seit 14.04 deaktiviert) sondern queried worker_heartbeats live (6 Worker, last_seen <10min). active_workers: finished_at-Query (immer 0 bei laufendem Batch) → COUNT(*) WHERE gmaps_docker_count>0 AND last_seen<5min. Verify: source=worker_heartbeats, 6 workers, active_workers=6, total_docker=32. Lektionen #150-#152.
CC18 Block A — Telegram Professionalisierung (CC_PROMPT 17) 19.04. ~15:00 (Commit 737c755)
3-Schicht-Redesign für ~90% Message-Reduktion (766→~80 msg/24h). (1) NOTIFICATION_CONFIG in telegram_utils.py: 15 suppress (pg_idle_killer, load_throttler, status_report, etc.) + 52 throttle (längere Intervalle: system_audit 1h, pipeline_health 4h, daemon_keeper 4h) + 7 instant (nur echte Notfälle: server_down, proxy_budget, spamhaus). (2) State-Change-Detection in system_audit_quick.py: State-File /tmp/audit_quick_last_state.json, nur bei CRITICAL↔WARNING↔OK Transitions Telegram senden (vorher: bei JEDEM */5 Run, 194 msg/24h). (3) Digest scripts/telegram_digest.py (NEU): 4× täglich (Cron 0 6,12,18,0), Dashboard-Summary mit Cluster-Status, KPIs, Alert-Summary, Top-3 Issues. Mobil-optimiert. (4) Bypass-Fix: gmaps_full_matrix_batch_activator.py curl→send_alert. Block B+C: STOPP-Bericht geliefert. Block B: 6 Cache-Poison-Endpoints identifiziert (~30min). Block C: Dedupe-Pipeline unvollständig, Resolution-Daemon fehlt (~2-3h).
CC17 — 8 P1-Alerts + Monitor-Validierung + ANO-Fixes (CC_PROMPT 16) 19.04. Abend (Commit dba3c16)
Alert-Coverage 37% → 45% (+8 neue Checks in pipeline_health_alert.py). Monitor-Validierung: 20 Tiles systematisch gegen 3 Quellen geprüft (Monitor-API / Briefing / DB). 16/20 OK, 2 Warnings (Shard-0 degraded self-resolving, quality_avg flat). ANO-1: Briefing daemons.online/total waren None → jetzt populiert (29/29) via _get_all_daemon_status() Summary-Counts. ANO-2: w2-reaktor-1 Orphan-Record gelöscht. 8 neue Alerts: (1) Table Bloat >50% WARNING / >200% CRITICAL, (2) Unused Indexes >500MB (via pg_class.relpages statt pg_relation_size I/O), (3) HR Name-Coverage <40% WARNING, (4) Telegram Unclassified >200, (5) GMaps Discoveries/24h <10k, (6) Description Throughput/h <5k, (7) Reaktor-Workers down, (8) Enrichment-Daemons (8 kritische gegen Heartbeats). Smoke-Test: desc_backlog 234k WARNING, dedupe 235k WARNING, HR Name 38.1% WARNING korrekt gefeuert. Plus: check_db_unused_indexes() in system_audit_full.py integriert (täglicher Vollaudit). Source-Freshness per-query statement_timeout='5s' gegen 30s-Timeout gefixt.
W4 Daemon-Akkumulation-Fix + daemon_keeper NameError 19.04. Mittag (Commits 5cd0aec→7fd0497)
Root-Causes: daemon_keeper crashte bei jedem Cron-Run mit NameError: name '_WC_W1' is not defined — seit Commit 866a364 (server_caps.json SSOT) kein Watchdog. Daemons akkumulierten unkontrolliert. domain_resolver ×10 (W1) · domain_email_booster ×14 (W3, unresponsive) · ats_email_enricher ×6 (W3) + ×1 (W2) + ×2 (W5) · contact_completer ×4 (W2) + ×2 (W1) · career_email_miner ×3 (W1) + ×1 (W2). Jede Instanz = ein paralleler SELECT auf job_advertisements (1.4M Rows) → W4 100% CPU. Fixes: (1) domain_resolver + domain_email_booster: PID-Lock fcntl.flock LOCK_EX LOCK_NB (Commit 5cd0aec). (2) contact_completer + career_email_miner: PID-Lock + Rsync alle Worker (Commit d280d7f). (3) ats_email_enricher: PID-Lock, W3 (13 Prozesse) + W2 + W5 Duplikate gekillt (Commit 7360cc8). (4) daemon_keeper.py: load_server_caps() + _WC_* VOR EXPECTED-Dict verschoben — Python evaluiert module-level Dict-Literals sofort (Commit 7fd0497). Alle Duplikate gekillt, fehlende Partitionen manuell restartet. Ergebnis: W4 Load 100% → 6.65 (unter Baseline 9.09), 6/6 Partition-Daemons mit PID-Lock, daemon_keeper läuft korrekt. Lektionen #177 (daemon_keeper NameError = Watchdog-Ausfall), #178 (PID-Lock in allen partition-aware Daemons), #179 (DataImpulse ETA = plan_remaining / burn).
W4 Stampede-Runde-2: contacts + momentum + enriched + VP-Matcher Throttle 19.04. ~02:40 (Commit de09ff8)
contacts/router.py: _contacts_cache per-Worker-Dict → Redis + Stampede-Lock (8× gleichzeitig, Lektion #175). companies/momentum.py: kein Cache → Redis 300s + Lock (6-8×). jobs/enriched.py: get_jobs_enriched Stampede-Lock + stale. 4 weitere admin_api.py-Endpoints (iq/quality-dashboard Lock-Loser-Bug, iq/dach-report, intelligence/salary, trends/hot-list). vp_matcher_daemon: Self-Throttle 11→20 (Pipeline-Baseline=14 aktive Queries, Matcher pausierte DAUERHAFT). W4 Load 90% CPU → 10.39, VP-Matcher Stage-1 aktiv. Lektion #176 (Throttle-Threshold muss über Pipeline-Baseline liegen).
W4 Stampede-Tiefenfix + VP-Matcher DB-Host 19.04. ~02:00 (Commits b969b46+3a0dfb7+2179c18)
@cached Decorator (9 Endpoints): Redis SET NX EX 120 + stale 3600s + wait-loop. matcher_monitor TTL: 15→300s (war kürzer als Query-Dauer 89s). crawler_stats: 7× COUNT(*) → mv_dashboard_kpis (130s→instant). claude_full_status: Lock-Loser Fall-Through Bug. _enrichment_stats(): Stampede-Lock. advertsdata_vp_matcher_daemon.py: DB_DSN hardcoded 127.0.0.1 → host-aware (Lektion #173). Lektionen #173 (hardcoded DB-Host auf Worker-Servern) + #174 (@cached ohne Stampede-Lock).
Quality Sprint Track B — NX-84 Admin Inspector + Customer Portal Upgrade 18.04.
Branch quality-frontend, 4 Commits, +1.293 Zeilen: Admin NX-84 Inspector (b4068c7): admin/src/pages/quality-inspector.tsx (+831) — Tier-Pyramide klickbar, Filter-Bar (Search, has_email/phone, source_category), Paginierte Tabelle mit Multi-Select, Detail-Drawer mit Score-Breakdown + Validation-Status + Dedupe-Matches + Actions (Email kopieren, Stelle öffnen), Bulk-Aktionen (dismiss_dedupe / mark_verified / set_tier_override), Excel+CSV Export (StreamingResponse), Demo-Mode ?view=demo (kuratierter astrein+email+phone), URL-Deep-Linking für alle Filter, 30s Auto-Refresh. 3 neue Components: QualityBadge + TierPyramid + ExportButton. Sidebar-Link in Layout.tsx + PartnerLayout.tsx. Customer Portal Quality-Upgrade (8a51642): 2 shared Components (QualityBadge + TrustBadge mit Verifiziert/Direkt/MX/Generisch/Ungeprueft). daten-qualitaet +Tier-Pyramide-Section + Trust-Metriken-Grid aus /customer-overview. search: min_quality=40 Default (Schrott raus) + neue Sort-Option "Beste Kontaktqualität" (trust_score). stellenanzeigen: min_score=40 Default. contacts: Default Min-Score 50→60 (zeigt nur okay+). hr-kontakte: Generisch-Warning ⚠ / Direkt-Kontakt-Badge ✓. Merge beider Branches (1f00141 + f505562): admin+frontend builds gruen, /quality-inspector HTTP 200 in 14ms, /customer-overview liefert astrein=47.266+validation=18.805. Sales-Demo ready für Sandro: /quality-inspector?view=demo. Lektionen #120-#124.
CC17 Block B — 7 Stampede-Lock Endpoints 19.04. ~19:35 (Commit 42d3ee0)
_with_lock() async Helper: Redis SET NX EX 120 + stale-Fallback 3600s + Lock-Loser wait. 7 Endpoints geschützt: dashboard (per-Worker Dict→Redis, 21ms), intelligence/quality (GROUP BY 1.4M, 20ms), auto-analyst/status (259→24ms), propagator/status (10.5s→49ms), tis/overview (936→26ms), aoe/queue (102→24ms), aoe/autonomy-status (323→22ms). Alle <50ms bei Cache-Hit.
CC17 Block C — Dedupe-Resolver 235k→5.8k pending (97.5%) 19.04. ~19:35 (Commit 42d3ee0)
scripts/dedupe_resolver.py (NEU): 3-Phasen Auto-Resolution + PID-Lock + Cron 0 2 * * *. Phase 1: 12.167 Garbage rejected (.png-URLs als Email). Phase 2: 13.800 resolved, 10.589 Jobs deaktiviert (höherer quality_score gewinnt). Phase 2b: firma_domain (sim≥80). Phase 2c: titel_ort (sim≥85). Phase 3: 203.348 not_duplicate (verschiedene Jobs, gleiche Firmen-Email). Erkenntnis: 98.9% der email_exact waren False Positives (Firmen-Sammel-Emails).
CC18 — Monitor-v2 Mission Control Dashboard 19.04. Abend (Commit f8c9ab6)
3-Tier Ops-Dashboard: (1) Status-Bar (Emerald/Amber/Rot, aus 3m lesbar auf 65" TV, clamp-Fonts), (2) 8 Key Metric Cards (Jobs, Email%, Grade-S, GMaps/24h, HR, Enrichment, Desc Backlog, Proxy), (3) 6 expandierbare Detail-Panels (Server Health, Daemons, ATS Spiders, Pipeline, Proxy Budget, Telegram). TV-Modus (>1600px, Panels geschlossen), Fullscreen (F-Taste), 30s Auto-Refresh, 1 API-Call, Dark Theme. URL: /monitor-v2 (ohne Login). Commit 45d7981: Auth-Wrapper entfernt.
Monitor-Fixes: Daemon-Tile + GMaps-Zombies 19.04. Abend
Daemon-Tile: META_KEYS Set (total, online) aus Zählung + Weitere-Gruppe ausgeschlossen — "2 offline: total, online" Bug behoben. GMaps-Cluster: 20.380 Zombie stuck-running Jobs zu pending reset. Worker-Filter (HAVING Clause + is_active Check) entfernt inaktive Server (W2, W5, vmi3195586). ETA-Berechnung: discoveries_24h als velocity statt total_done. vp-build Tag für Auto-Reload aktualisiert.
CC19 Rollback + CC19b Minimal-Fix 19.04. ~23:00
CC19 Viewport-Refactor (Commit 06fc09c) zurückgerollt — px→vw/vh/clamp hat Layout bei <1920px-Viewports zerstört (Kacheln überlappen, Panels brechen), Monitor war nie fluide designed (fixed grid-template-rows `46px 72px 224px 1fr 26px`). Rollback: git checkout monitor-pre-refactor -- monitor/index.html. Ersatz CC19b (2-Zeilen-Fix): (1) zoom-Media-Queries aggressiver: 1.0 default / 1.6 @2560px+ / 2.2 @3840px+ (vorher 1.5 @2560-3199 + 2.2 @3200+ + body{zoom:0.80} override), (2) body{overflow-x:hidden}html{overflow-x:hidden} statt body{zoom:0.80}. Keine Layout-Änderung, keine px→vw, kein clamp(). scripts/monitor_viewport_refactor.py gelöscht. Tag monitor-pre-refactor bleibt. Lektion #184: Viewport-Refactor setzt fluide-designed Layout voraus — bei fixed-width-Design nur zoom-Media-Queries sicher.
W1 SMTP-Verify-Bypass — Grade-S 12.041 → 15.081 (+3.040, +25.2%) 19.04. ~22:10 (Commit f621627)
Root-Cause: Master-IP 161.97.79.192 auf Spamhaus CSS gelistet. ALLE SMTP-RCPT-Probes gegen Outlook/Exchange-MX liefern 550 Service unavailable, Client host blocked using Spamhaus = systematische False-Negatives. Master-Batch-Verify seit 18.04 11:21 stillgelegt. ~46k hr_contacts-Emails fehlerhaft als invalid/timeout/refused gespeichert. Fix: Pipeline migriert nach W1 (173.212.217.37 Spamhaus-clean). quality_engine/ rsynced, dnspython via pip --break-system-packages, config.py DB_DSN host-aware, Tier grade_bc_promote in batch_verify.py (B/C-Kontakte mit email+phone+name+position, non-generic). NOT EXISTS-Filter nur gegen overall_status='valid' → Re-Verify der Master-False-Negatives. Smoke 50: 9s/5.6/s/42 valid. Full-Run 5000: 463s/10.8/s/2726 valid (54.5%)/0 Errors. grade_after_verify.sql: 3.040 B→S, 3.235 email_verified neu. Cron W1: 15 3 * * * 2000 Emails/Tag + automatic grade_after_verify. Pool ~48k Rest (∼24 Tage). KQI: 82.40% → 83.0% (+0.6pp). Master-SMTP bleibt deaktiviert bis Spamhaus-Delisting (Sandro A2). Lektionen #180-#182.
CC28b+c — PDF-Extractor Multilingual Anker (DE/FR/EN) 20.04. ~08:03 (Commits 2a7c1fc+910367d)
Root-Cause PDF-Pipeline 0% Success: PDF-Extractor auf W3 mit aktivem DataImpulse-Proxy hatte stundenlang 0/50 Success pro Batch. Source dokumente.anzeigedaten.de erreichbar via Proxy (HTTP 200), aber extract(pdf) returnte alle Felder None → [nicht extrahierbar]-Writes. Deep-Diagnose (step-by-step): (1) curl direct HTTP 000 (IP-Ban erwartet), (2) curl via Proxy HTTP 200, (3) aiohttp lädt PDFs (73 KB DE-Kleinanzeige, 426 KB Castorama Chambéry FR), (4) extract(pdf) alle None, (5) Inspection: PDFs sind DE-Kleinanzeigen + FR + EN gemischt, aber anchors-Liste nur DE-Enterprise ("Ihre Aufgaben", "Stellenbeschreibung"). Fix: Anker erweitert auf DE+FR+EN (22 Terme): DE "Beschreibung" + FR "Les missions du poste"/"Description du poste"/"Profil recherché"/"Responsabilités" + EN "Job description"/"Responsibilities"/"Tasks". Live-Verify W3 08:01-08:03: Batch 1 39/50 (78%), Batch 2 40/50 (79%), Batch 3 48/50 (84.7%). Lektion #191: Bei 0% Success niemals vorschnell "Source DOWN" — immer Parse-Logik step-by-step. Multi-Lang-Pipelines brauchen DE+FR+EN-Anker (advertsdata importiert EU-weit).
Session 20.04 CC20–CC28 — Spider-Fixes + Monitor + Cross-Enrichment 20.04. ~02:00-05:30 (18+ Commits)
CC20 Cross-Enrichment: +4.529 Emails / +9.638 Phones via intra-Firma + GMaps + AD Matching. Grade-S 15.081→17.933. KQI blieb ~82.4% weil Firma-generic-Emails (info@) nicht im Benchmark zählen → Lektion #186. CC21 data_sources API: /api/monitor/data-sources + pipeline_health_alert.check_data_sources_down() (HTTP-Call statt Direct-SQL). 5 ATS-Spider als DOWN aufgedeckt → Lektion #187. CC22 Spider-Freshness: MAX(GREATEST(crawled_at, last_seen_at, updated_at)) statt nur MAX(crawled_at). 5 False-DOWN → LIVE. UPSERT-Pfade sind inkonsistent (talention SELECT-then-UPDATE setzt nur last_seen_at) → Lektion #188. CC23 DSN-Cleanup + Workday-Retry: crawl_workday_fix.py/fix_softgarden_ashby.py host-aware. Workday 7d-Retry-Gate (Pool 20k→6k, err-rate 99.6%→normal) → Lektion #189. CC24 2 Builder-Functions: data_sources in BEIDEN (_monitor_full_sync + _build_full_status) synchronisiert → Lektion #190. Plus: Jobware Spider live W5 (Cron 0 */6, URL /job/<slug>-<id>). CC25/25b Monitor max-height:420px zurück + overflow-y:auto (Layout safe). CC26 batch_ats_discovery defaultdict-Init + Fingerprinter 22→49 Patterns. CC27 successfactors Pattern entfernt (matched SAP-Infra-Subdomains wie boomi/sftp/community, 39 Junk-URLs deaktiviert). 49→48. CC28 Empty-Tiles Fix + Umantis Spider (Cron 15 */6) + ATS idle-dim opacity 0.35.
Desc-Backlog Diagnose: Memo → Live 22.924 (98.46% Coverage) 19.04. ~22:00
Memo war veraltet (232k). Live-Messung: 22.924 / 1.485.840 aktive Jobs = 98.46% Description-Coverage. Breakdown: 12.834 in letzten 24h (laufende Pipeline), 10.486 in letzter 1h (Fresh-Ingest). Hot Spots: ats_smartrecruiters 12.222 (15.5% der SR-Jobs) · kleinanzeigen 5.178 · ats_workable 4.054. Kein Handlungsbedarf — Normal-Pipeline-Lag, wird laufend abgebaut.

Aktueller Stand: 41 Portal-Pages + 15 Landing-Pages + 40 Admin-Seiten

MARKT (9)
Dashboard, Stellenanzeigen, HR-Kontakte, HR-Firmenprofil, Schnellsuche, Radar, Radio, Unternehmen, Engpass
TOOLS (3)
Info-Agenten, Kunden-Radar, Export
INTELLIGENCE (11)
Momentum, Placement, Evolution, Contacts, GVP, Skill-Map, DACH-Report, Analytics, Quellen-Health, Innovationen, Daten-Qualität v2
AKQUISE (4)
Outreach-Center, Template-Editor, Setup-Guide, Tagesplanung
ADMIN (3)
User-Management, Portal-Analytics, NX-84 Quality Inspector
Quality Sprint (18.04. live): Tier-Pyramide astrein 47.266 (×3 über Prompt-Ziel) · gut 443.681 · Validation 18.805 Emails (88.4% MX) · Dedupe 217.665 email_exact Kandidaten · trust_score 10.041 Jobs · Schrott-Filter Customer Portal aktiv
Enrichment-Pipeline: 1.41M aktive Jobs · 662k Firmen · 141k mit Email · 84.8% Description · 62.4% Email-Rate · 35.4% Phone · Ø Quality-Score 48.1 · Dedupe 235k→5.8k (97.5% resolved)

Nächste Schritte (A–Z sortiert)

A — ATS-Spider Audit (ats_join + breezy + pinpoint + icims)
ats_join 13.6 Tage off. Vermutlich hardcoded-DSN-Pattern (Lektion #96). Audit: grep -rn "DB_DSN.*127.0.0.1" scripts/.
B — Domain vakanzpuls.de aktivieren
Blockt Outreach an 3.214 Kontakte, SMTP-Verifier, Impressum, Landing. SANDRO-BLOCKER #A1.
C — Erstkunden-Onboarding
Domain live, Impressum vollständig, Stripe-Preise, Portal-Demo. Abhängig von B + E + F.
D — EU Art.27 Vertreter (DRINGEND)
activemind.legal ~50€/Mo. Muss VOR Outreach erledigt sein. DSGVO-Pflicht für nicht-EU-Kontakte.
E — GMaps Phase 3+4 (Query-Generator v4 + Jobs-Bridge)
Phase 3: PLZ-DE + AT/CH + Recursive für 200k+ pending pool. Phase 4: gmaps_to_sources.py als Cron aktivieren (Bridge INAKTIV). Aktuell: 595k Discoveries, 108k pending.
F — Impressum + DSGVO + AGB Texte finalisieren
Impressum finalisieren, datenschutz@vakanzpuls.de einrichten, AV-Verträge (Contabo, SendGrid). SANDRO-BLOCKER.
G — HR Name-Coverage erhöhen (36.8% → 50%+)
Aktuell 61.5k/161k mit Name. Quelle: GVP-Matching, Impressum-Crawler, Career-Page-Mining. Impact: KQI steigt, Grade-S wächst.
H — Monitor-v2 Ausbau (Sparklines + Trends)
Sparklines für 24h-Trends in Metric-Cards. pipeline_metrics_hourly als Datenquelle. Trend-Pfeile (↑↓) vs. gestern.
I — Outreach erste Welle (nach Domain)
OUTREACH_ENABLED=true, Kampagne starten. Template-Editor + Setup-Guide + CP-Checkliste live. 3.214 GVP-Kontakte bereit. Wartet auf Domain (B).
J — Sales-Demo Vorbereitung (18.-30.04.)
Demo-URL admin.../quality-inspector?view=demo. 47k Astrein-Jobs + Excel-Export. Dedupe Backlog 235k→5.8k erledigt.
K — SMTP-Verify auf GVP-Subset (Sandro-Freigabe)
NeverBounce ~$50/8.5k Emails. Nur auf GVP + Grade-S+A. Würde KQI von 80.8% auf ~85% pushen.
L — Spamhaus CSS-Delisting
161.97.79.192 auf CSS (SBL-Subset). Delisting-Request bei check.spamhaus.org. Blockt SMTP-Outreach. SANDRO-BLOCKER #A2.
M — Master-Plan v2 Enrichment Pipeline (11.-17.05.)
E1 Schema + E2 NER (29.6% Hit-Rate) + E3 Impressum-Crawler (8.5k/d, 50% Hit-Rate) + E4 OffeneRegister-Cross-Reference. Hevelio-Fix bestätigt (Jacek+Julian is_outdated=TRUE). Auto-Promote Hybrid-Trigger (big/mid/small batch). Lektionen #283–#308.
N — Self-Healing Watchdog System (Sprint F+R4, 11.-17.05.)
Watchdog Layer 2 (Productivity+Bandwidth+SMTP) + 3 Auto-Heal-Actions (NER-restart, advertsdata-trigger, crontab-restore) + Cooldown + Auto-Disable nach 3 failures. Anti-Cron-Drift hourly check. claude_md_size_watchdog täglich.
O — Briefing-Cache-Fix (Sprint 4, 11.05.)
mv_hr_stats_briefing erweitert um Total-Spalten parallel zu DACH. Briefing zeigt jetzt 185.191 contacts statt 143k (DACH-subset). unique_emails 138.574 jetzt im API. premium-Block korrigiert.
P — Monitor v9 Drag-and-Drop PAUSIERT (17.05. spät)
Refactor pausiert nach 6h Aufwand. monitor_v9.html bleibt als Experiment, Live-Monitor unter `/` unverändert stabil. Whitespace-Problem strukturell (Lektion #310 flex:1+scrollHeight Math-Bug). Re-Take frühestens nach E5/E6 Pipeline-Demo-Ready. Lektionen #309 + #310.
Q — Day-Fix Pool-Stagnation + Monitor-504 + Telegram (18.05.)
Pool RESOLVED: 879 echte HR-Contacts inserted (lifetime promoted 0→1.332). Function v3 mit Triple-Check + ON CONFLICT DO NOTHING. NER Pre-Filter hr_company_id (38→100% company-coverage). Thresholds 50k/5k/1k→10k/2k/500. Monitor /api/monitor/full 342s→0.014s warm (Cache-TTL 20s→90s + Pre-Warmer */1). Telegram-Tweaks: T2 Status-Change-Filter + T3 Auto-Heal-Backoff (5-Strike + 0/30min/2h/6h/24h-STOP). Lektionen #311–#315.
R — Mo-Marathon 01.06 Customer-Portal Quality-Wende (13 Commits)
12+ sequenzielle Briefe, 3 Workflows, 20 Tasks. Skomi-Eskalation 14:00 "Portal Katastrofe" → Bundle Phase-E Total-Audit (87 Findings, 11 P0-Issues). γ-Strukturfix source_watchdog: Cron `*/2`→`7,22,37,52` + flock + application_name + BATCH_SIZE=5000 + SAVEPOINT pro Batch + WHERE stale-Filter. Lock-Cascade gmaps_reaktor 5-PIDs weg, W4-Load 18.77→12.05. Re-Audit: 4 RESOLVED (Anti-Dom 10/10 distinct DACH, /firmen Page-1 0→20, SMTP-cleanup 24.657→2.775 -89%, Hot-List DACH) + 1 FALSE-POSITIVE + 2 OFF-PEAK + 3 QUICK-FIX. **Late-Evening Drama (17:15):** Skomi-Eskalation "Portal alles weg" — Wurzel war Frontend-Build mit falschem NEXT_PUBLIC_API_URL-Override im Phase F Item 2 (Lektion #395). Recovery via Rebuild OHNE Override. Plus #79 statement_timeout 8s→3s (4.5x Speedup, 18.2s→4.0s) + **#78 q-Param-Alias-Fix** (enriched.py:84 `Query(None, alias="q")`, q=bosch liefert jetzt Bosch-Jobs). Off-Peak Bundle scheduled fuer 02:00 02.06 (mv_jobs_enriched + Trgm + mv_jobs_searchable REFRESH mit Auto-Gate W4<13.5). 5x Lektion #382 Schema-Drift gefangen, 3x Lektion #275 Cron-Drift LIVE. 4 NEUE Lektion-Kandidaten #392-#395.
23
Parkplatz
Offene Punkte die auf externe Trigger warten

Sandro-Blocker (ohne ihn kein Fortschritt)

  • Domain vakanzpuls.de — blockt Outreach, SMTP, Landing, Impressum
  • Spamhaus CSS-Delisting — check.spamhaus.org, blockt SMTP-Outreach
  • NeverBounce (~$750/250k) für Bulk-Email-Verification
  • AV-Verträge (Contabo, SendGrid, IPRoyal)
  • Impressum + DSGVO + AGB Texte
  • EU Art.27 Vertreter (~50€/Mo)

Technisch offen

  • GMaps Phase 3+4 (Query-Generator v4 + Jobs-Bridge)
  • HR Name-Coverage 36.8% → 50%+
  • Monitor-v2 Ausbau (Sparklines + 24h-Trends)
  • ATS-Spider Audit (ats_join 13.6d off)
  • desc_pct 84.8% → stabil >85%
  • 10 Redis-backed Endpoints ohne Stampede-Lock (P3)
24
Advertsdata Proxy-Pipeline (IPRoyal)
IP-Bann-Workaround · Residential Proxy · Quota-Tracking · Auto-Resume

Hintergrund — Was passierte am 13.04.2026

Um 14:29 UTC stoppten alle direkten Inserts aus db.advertsdata.com. Diagnose via tcpdump: SYN-Pakete gehen raus, kein SYN-ACK zurück — silent drop am Ziel. Test aller 6 Server: M, W1, W2, W3, W5 alle blockiert; nur W6 (164.68.123.85, kein Advertsdata-History) kam noch durch ⇒ klassischer IP-Bann nach intensivem Scraping.

Lösung — IPRoyal Residential Proxy

Plan

  • 10 GB / $52.50/Monat Pay-As-You-Go
  • Endpoint: geo.iproyal.com:12321
  • Hard-Cap: 9 GB (1 GB Puffer)
  • Residential rotating IPs (echte deutsche Nutzer-IPs)
  • Reach: ~2 Mio Pages bei 5 KB/Page

Performance

  • ~5 KB pro Page (statt ~500 KB Playwright)
  • Live: 50/50 OK in 97s, 31 req/min @ 2 Worker
  • Hochskaliert (4W): ~85k Pages/Tag
  • Backlog (1.06M) bei 85k/Tag = ~12 Tage

Komponenten

Scraper

scripts/advertsdata_proxy_scraper.py

Lean requests + BeautifulSoup. Modi: --gap-filler (default) / --range START-END / --ids 1,2. Threading via --workers N. Backoff bei 403/429 (3× sleep, neue Session).

Cron: */15 * * * * — 200 IDs, 2 Worker

Quota-Tracker

scripts/iproyal_quota_check.py + Cron */30

State-File /tmp/advertsdata_proxy_bandwidth (Bytes | Monat). Telegram-Alerts 1× pro Schwelle/Monat: 50% / 75% / 90% / 100%. Tagesreport 09:00 mit verbleibendem Kontingent.

Watchdog-Härtung

scripts/advertsdata_watchdog.py

Pre-Check is_source_reachable(). Bei Source-Down: SIGSTOP auf alle Worker + EIN Info-Alert. Bei Source-Up: SIGCONT + Recovery-Alert. State-File /tmp/advertsdata_source_state — idempotent, kein Spam.

Monitor-Tile

Rechts unten in der p-right Spalte. Progress-Bar mit Farb-Schwellen (grün <50% / gold <75% / gelb <90% / rot ≥90%).

Endpoint: /api/monitor/full → Feld iproyal (used_gb, plan_gb, cap_gb, pct_plan, remaining_gb).

Direkte Worker-Strategie

Die 5 alten direkten Worker (M+W1+W2+W3+W5) sind via SIGSTOP pausiert. Watchdog prüft regelmäßig Source-Reachability — bei Auto-Lift des IP-Banns (typisch 24-48h) erfolgt automatisch SIGCONT + Recovery-Telegram. W6 bleibt unberührt (GMaps-only, keine Advertsdata-Last).

Commits

  • 6b098ce Watchdog Pre-Check + SIG-Pause
  • f47232f IPRoyal Proxy + Quota-Tracker + Monitor-Tile
VakanzPuls — Projektdokumentation v2.9 · Mo-Marathon 01.06 ABEND + #78 + #79 + #80 Late-Evening-Recovery
Stand: 01.06.2026 (~18:20 CEST) · Nächste ID: Off-Peak-Bundle 02:00 02.06 (Auto-Trigger) · Lektionen #32–#395 · Mo-Marathon: 13 Commits, 12+ Briefe, 3 Workflows, 20 Tasks · Customer-Portal: 6/6 Sektionen LIVE post-Recovery, q=bosch liefert Bosch-Jobs · Re-Audit: 4 RESOLVED + 1 FALSE-POSITIVE + 2 OFF-PEAK + 3 QUICK-FIX (alle gefixt) · SMTP-cleanup: 24.657→2.775 (-89%) · OPEN: Off-Peak Bundle 02:00 Di (Auto), #69 Hevelio-Search Off-Peak, Domain vakanzpuls.de (Sandro)
Team: Michael (Tech/CTO) · Sandro (Sales/GF)
GitHub: 0xxCool/vakanzpuls · Branch: master
Session 19.04: CC16-CC19+Rollback (Monitor-v2, CC19b zoom-only, W1-SMTP-Bypass, Alerts, Telegram, Stampede, Dedupe)