# Projekt-Learnings — Schaeffler Automat ## Format **Datum | Kategorie | Problem → Lösung** --- ## Learnings ### 2026-01-15 | Architektur | Backend-Port-Konflikt **Problem:** FastAPI standardmäßig auf Port 8000 — war auf dem Entwicklungsrechner belegt **Lösung:** Port 8888 in `docker-compose.yml` und Vite-Proxy konfiguriert **Für künftige Projekte:** Port früh festlegen und in CLAUDE.md dokumentieren --- ### 2026-01-20 | Datenbank | SQLAlchemy trackt key-value-Store-Mutations nicht **Problem:** Admin-Einstellungen (`system_settings`) wurden via ORM gespeichert, Änderungen wurden nicht persistiert **Ursache:** SQLAlchemy erkennt keine Mutation an einem bereits geladenen Objekt wenn nur ein Value-Feld geändert wird **Lösung:** Direktes SQL `UPDATE` via `op.execute()` statt ORM-Mutation in `admin.py` **Für künftige Projekte:** Key-Value-Stores immer mit direktem SQL oder `session.execute(update(...))` verwalten --- ### 2026-01-25 | Render-Pipeline | Blender ignoriert STEP-Einheiten (mm vs. m) **Problem:** STEP-Dateien sind in Millimetern, Blender arbeitet intern in Metern → 50mm-Lager erscheint 50 Meter breit, Kamera framt falsch **Lösung:** `_scale_mm_to_m(parts)` Helper in allen 3 Render-Scripts: `part.scale = (0.001, 0.001, 0.001)`, Transform anwenden **Betroffene Dateien:** `blender_render.py`, `still_render.py`, `turntable_render.py` **Für künftige Projekte:** Einheiten-Konvertierung direkt nach STL-Import, vor jeder Kamera-Kalkulation --- ### 2026-01-28 | Render-Pipeline | Blender 5.0 hat `scene.node_tree` entfernt **Problem:** `_setup_bg_compositor()` rief `scene.node_tree` auf (in Blender 5.0 entfernt) → Python-Exception → Blender exitete mit Code 0 → Flamenco markierte Task fälschlicherweise als "completed" **Lösung:** `_setup_bg_compositor()` aus Setup + Render-Script entfernt; bg_color-Kompositing in FFmpeg verschoben (`-f lavfi -i color=...` + overlay-Filter) **Wichtig:** Immer `try: main() except SystemExit: raise except Exception: traceback; sys.exit(1)` in Blender-Scripts — sonst verschluckt Blender Python-Exceptions **Für künftige Projekte:** Nach Blender-Major-Updates alle API-Calls prüfen; Exception-Guard ist Pflicht --- ### 2026-02-05 | Material-System | Material-Alias-Lookup-Reihenfolge falsch **Problem:** `Steel--Stahl` war sowohl ein kanonischer `Material.name` als auch ein Alias für `SCHAEFFLER_010101_Steel-Bare`. Der Lookup prüfte zuerst den exakten Namen und fand `Steel--Stahl` — Blender konnte diesen Namen aber nicht in der Library finden **Lösung:** Lookup-Reihenfolge in `material_service.py` umgekehrt: **Aliases zuerst**, dann exakter Name, dann Pass-through **Für künftige Projekte:** Alias-System immer so designen dass Aliases Vorrang haben; nie zwei Lookup-Pfade mit überlappenden Treffern --- ### 2026-02-10 | Render-Pipeline | Blender-Template zerstört HDRI/World **Problem:** Im Template-Modus (Mode B) wurden trotzdem Auto-Lights und eine neue World erstellt → überschrieb den HDRI aus dem .blend-Template → falsche Beleuchtung **Ursache:** Auto-Licht- und World-Setup-Code lief bedingungslos, nicht nur im Mode A **Lösung:** In Template-Mode werden Lights, World und Color-Management-Override vollständig übersprungen; nur die Kamera wird ggf. neu berechnet **Betroffene Dateien:** `still_render.py`, `turntable_render.py`, `schaeffler-still.js`, `schaeffler-turntable.js` --- ### 2026-02-15 | Celery | Blender-Queue-Flooding durch falsche Concurrency **Problem:** Alle Celery-Tasks (schnelle Metadata-Extraktion + langsamer Blender-Render) liefen auf `step_processing` mit concurrency=8 → 8 Workers schickten gleichzeitig Requests an blender-renderer (der nur 1 gleichzeitig verarbeiten kann) → 7 davon liefen in 300s-Timeout → blockierte die gesamte Queue **Lösung:** Pipeline aufgeteilt: - `process_step_file` (step_processing, concurrency=8): nur schnelle Metadata-Extraktion (<2s), queut dann → - `render_step_thumbnail` (thumbnail_rendering, concurrency=1): Blender-Call, niemals timeout **Neuer Service:** `worker-thumbnail` in `docker-compose.yml` mit `--concurrency=1` **Für künftige Projekte:** HTTP-Services die nur 1 Request gleichzeitig verarbeiten können IMMER auf einer separaten Queue mit concurrency=1 laufen lassen --- ### 2026-02-18 | Frontend | Tailwind CSS-Variablen inkompatibel mit opacity-Syntax **Problem:** `bg-surface/50` oder `bg-surface` (wenn `--color-bg-surface` ein Hex-Wert ist) generiert `rgb(var(--color-bg-surface) / 0.5)` — invalides CSS, weil `rgb()` keine Hex-Werte als Channel-Input akzeptiert → Hintergrund transparent **Ursache:** Tailwind erwartet CSS-Variablen mit RGB-Channel-Format (`255 255 255`), nicht Hex (`#ffffff`) **Lösung:** Inline-Style verwenden: `style={{ backgroundColor: 'var(--color-bg-surface)' }}` **Für künftige Projekte:** Entweder CSS-Variablen im RGB-Channel-Format definieren, oder konsequent inline styles für variable Farben --- ### 2026-02-20 | STL-Cache | Three.js-Renderer nutzte tempfile → kein Download möglich **Problem:** Three.js-Renderer konvertierte STEP→STL in ein tempfile und löschte es anschließend → STL-Download-Endpoint fand keine Datei **Ursache:** Three.js war ursprünglich nur für Thumbnails gebaut, STL-Cache-Konvention (`{stem}_low.stl` neben STEP-Datei) wurde nicht implementiert **Lösung:** Persistent cache path: `step_path.parent / f"{step_path.stem}_low.stl"`, cache-hit-check vor Konvertierung, kein `unlink()` mehr **Für künftige Projekte:** STL-Cache-Konvention (`{step_stem}_{quality}.stl` neben STEP-Datei) von Anfang an in allen Renderer-Services einhalten --- ### 2026-02-20 | STL-Cache | blender-renderer fehlte /convert-stl Endpoint **Problem:** Für Produkte die mit Blender gerendert wurden war kein STL-Cache vorhanden wenn nicht explizit gerendert wurde (blender-renderer renderte + konvertierte in einem Schritt, aber STL wurde nicht persistiert) **Lösung:** Neuer `/convert-stl` Endpoint in `blender-renderer/app.py`: konvertiert STEP→STL ohne Render, persistiert Cache. Neuer Celery-Task `generate_stl_cache` auf `thumbnail_rendering`-Queue. Admin-Funktion "Generate Missing STLs" zum Batch-Nachfüllen --- ### 2026-02-22 | Material-System | Fehlender Alias blockiert Material-Replacement **Problem:** Produkt F-803422.01.TR2 (SA-2026-00080) renderte ohne Materialersetzung. Material "Stahl v2" war korrekt in der UI gespeichert, aber weder in `materials` noch in `material_aliases` vorhanden **Ursache:** Alias-Seeding aus Excel deckte nicht alle Varianten der deutschen Materialbezeichnungen ab **Lösung:** Alias direkt in DB eingetragen: `"Stahl v2"` → `SCHAEFFLER_010101_Steel-Bare` **Für künftige Projekte:** Bei Render ohne Materialersetzung immer zuerst `resolve_material_map()` debuggen und Alias-Tabelle prüfen; Alias-Seeding regelmäßig mit neuen Excel-Varianten erweitern --- ### 2026-02-25 | Frontend | canDispatch-Bedingung zu restriktiv **Problem:** "Dispatch Renders"-Button war nicht sichtbar obwohl der Auftrag offene Render-Zeilen hatte **Ursache:** `canDispatch` enthielt `&& hasRetryable` — Button erschien nur wenn pending/failed/cancelled-Zeilen vorhanden waren, nicht wenn alle Zeilen "pending" im Erstauftrag **Lösung:** `hasRetryable`-Bedingung entfernt; Button ist immer sichtbar wenn Auftrag im richtigen Status und User privilegiert ist **Für künftige Projekte:** Aktions-Buttons nicht zu stark von abgeleiteten Zuständen abhängig machen; lieber im Backend validieren --- ### 2026-02-28 | Frontend | MaterialInput-Dropdown ohne Hintergrund **Problem:** Dropdown der Material-Suchfeld-Komponente erschien transparent — Text über dem Hintergrund kaum lesbar **Ursache:** `bg-surface` Tailwind-Klasse + CSS-Variable mit Hex-Wert (siehe Learning 2026-02-18) **Lösung:** `style={{ backgroundColor: 'var(--color-bg-surface)' }}` für Dropdown-Container, Group-Header und Sticky-Button **Datei:** `frontend/src/components/shared/MaterialInput.tsx` --- ### 2026-03-06 | Refactor | .gitignore `core` trifft Verzeichnisse **Problem:** `.gitignore` enthielt `core` als Regel (für core dump files) — Git ignorierte damit auch `backend/app/core/` Verzeichnis **Lösung:** Regel zu `/core` umbenannt (Root-relative Regel trifft nur `/core` Datei, nicht verschachtelte `core/`-Verzeichnisse) **Für künftige Projekte:** Immer Root-relative Pfade (`/core`) für Dateien im Root-Verzeichnis nutzen --- ### 2026-03-06 | Architektur | Blender-HTTP-Service vs. direkter Subprocess **Problem:** `blender-renderer` als Flask/FastAPI HTTP-Microservice war ein Single-Point-of-Failure (max. 1 concurrent Request), kein Scaling möglich, HTTP-Overhead bei jedem Render **Lösung:** Render-Worker als Celery-Container (`render-worker/`) — Blender direkt via `subprocess.run` ohne HTTP. `is_blender_available()` prüft `BLENDER_BIN` env var für Kontext-Detection **Wichtig:** `step_processor.py` erkennt über `BLENDER_BIN`-Env ob Blender im aktuellen Container verfügbar ist — Backend-Container fallen auf Pillow zurück **Für künftige Projekte:** Subprocess-basierter Renderer > HTTP-Microservice für blocking compute tasks --- ## Offene Fragen - [ ] Azure AI Credentials für Phase 4 (Bildvalidierung) noch nicht konfiguriert - [ ] Flamenco GPU-Support nur mit NVIDIA — AMD/CPU-Fallback fehlt - [ ] Material-Alias-Seeding deckt noch nicht alle deutschen Materialbezeichnungs-Varianten ab - [ ] Turntable-Animation: bg_color via FFmpeg-Overlay — Qualität bei Transparenz-Edges prüfen