Commits vergleichen

2 Commits

Autor SHA1 Nachricht Datum
Claude Code
cbfb608471 feat(translator): Feature-Flag TRANSLATOR_ENABLED zum Abschalten
Ueber die ENV-Variable TRANSLATOR_ENABLED (default true) kann der
Translator-Agent komplett deaktiviert werden. Wenn false:
- translate_articles steigt mit return [] aus, ohne Claude-Calls
- Fremdsprachige Artikel bleiben unuebersetzt (headline_de/content_de NULL)

Hintergrund: Bei Lage 6 Irankonflikt sind 10.210 Artikel ohne DE-Uebersetzung
aufgelaufen. Pro Refresh werden 2042 Batches sequentiell gestreamt
(~25s/Batch -> 13.5h Gesamtdauer pro Refresh), was den Pipeline-Step
factcheck blockiert und die Queue lahmlegt. Bis das Performance-Thema
geloest ist (Parallelisierung, Relevanz-Filter, Hard-Cap), wird der
Agent live deaktiviert. Zustand spaeter ueber .env wieder aktivierbar.

Live-.env wurde mit TRANSLATOR_ENABLED=false ergaenzt.
2026-05-03 20:43:39 +00:00
Claude Code
e517de7404 fix(orchestrator): Auto-Refresh nicht direkt nach Cancel/Error neu einreihen
Der Auto-Refresh-Scheduler hat seinen letzten relevanten refresh_log-Eintrag
bisher mit Filter status IN (completed, running) gesucht. Cancelled- und
Error-Laeufe wurden ignoriert, der davor liegende Completed wurde genommen.
Ergebnis: Direkt nach Cancel oder Error wurde der Slot als faellig gesehen
und nach 60 Sekunden wieder eingereiht (Endlos-Loop bei Iran-Konflikt heute,
4x error in Folge ohne Pause).

- main.py: Filter erweitert auf status IN (completed, running, cancelled, error)
- orchestrator.py: Queue-Cancels schreiben jetzt auch einen cancelled-Eintrag
  ins refresh_log via _log_queued_cancellation (vorher: stiller Discard,
  kein Fingerabdruck im Log -> Auto-Refresh erkannte den Cancel nie)

Wirkung: Nach Cancel oder Error startet die Lage erst beim naechsten
regulaeren Slot wieder. refresh_mode bleibt unveraendert.
2026-05-03 19:30:02 +00:00
4 geänderte Dateien mit 38 neuen und 2 gelöschten Zeilen

Datei anzeigen

@@ -489,6 +489,9 @@ class AgentOrchestrator:
logger.info(f"Lage {incident_id} aus Warteschlange entfernt (removed={removed})")
# refresh_log-Eintrag schreiben, damit Auto-Refresh nicht im naechsten Tick erneut einreiht
await self._log_queued_cancellation(incident_id)
# Send cancelled event
if self._ws_manager:
try:
@@ -639,6 +642,28 @@ class AgentOrchestrator:
finally:
await db.close()
async def _log_queued_cancellation(self, incident_id: int):
"""Schreibt einen cancelled-Eintrag fuer einen Queue-Abbruch (Lage war noch nicht laufend).
Verhindert, dass der Auto-Refresh-Scheduler im naechsten Tick sofort wieder einreiht."""
from database import get_db
db = await get_db()
try:
cur = await db.execute("SELECT tenant_id FROM incidents WHERE id = ?", (incident_id,))
row = await cur.fetchone()
tid = row["tenant_id"] if row else None
now_str = datetime.now(TIMEZONE).strftime("%Y-%m-%d %H:%M:%S")
await db.execute(
"""INSERT INTO refresh_log (incident_id, started_at, completed_at, status,
trigger_type, error_message, tenant_id)
VALUES (?, ?, ?, 'cancelled', 'manual', 'Aus Warteschlange entfernt', ?)""",
(incident_id, now_str, now_str, tid),
)
await db.commit()
except Exception as e:
logger.warning(f"Konnte Queue-Cancel nicht in refresh_log loggen: {e}")
finally:
await db.close()
async def _mark_refresh_failed(self, incident_id: int, error: str):
"""Markiert den laufenden Refresh-Log-Eintrag als error."""
from database import get_db

Datei anzeigen

@@ -12,7 +12,7 @@ import logging
import re
from agents.claude_client import call_claude, ClaudeUsage, UsageAccumulator
from config import CLAUDE_MODEL_FAST
from config import CLAUDE_MODEL_FAST, TRANSLATOR_ENABLED
logger = logging.getLogger("osint.translator")
@@ -230,6 +230,13 @@ async def translate_articles(
if not articles:
return []
if not TRANSLATOR_ENABLED:
logger.info(
"Translator deaktiviert (TRANSLATOR_ENABLED=false), %d Artikel uebersprungen",
len(articles),
)
return []
all_translations = []
for i in range(0, len(articles), batch_size):
batch = articles[i : i + batch_size]

Datei anzeigen

@@ -41,6 +41,10 @@ OUTPUT_LANGUAGE = "Deutsch"
# In Kundenversion auf False setzen oder Env-Variable entfernen
DEV_MODE = os.environ.get("DEV_MODE", "true").lower() == "true"
# Feature-Flag: Translator-Agent (Haiku) komplett deaktivieren.
# False = keine Uebersetzungen mehr, fremdsprachige Artikel bleiben unuebersetzt.
TRANSLATOR_ENABLED = os.environ.get("TRANSLATOR_ENABLED", "true").lower() == "true"
# RSS-Feeds (Fallback, primär aus DB geladen)
RSS_FEEDS = {
"deutsch": [

Datei anzeigen

@@ -124,7 +124,7 @@ async def check_auto_refresh():
# Letzten abgeschlossenen oder laufenden Refresh pruefen
cursor = await db.execute(
"SELECT started_at, status FROM refresh_log WHERE incident_id = ? AND status IN ('completed', 'running') ORDER BY id DESC LIMIT 1",
"SELECT started_at, status FROM refresh_log WHERE incident_id = ? AND status IN ('completed', 'running', 'cancelled', 'error') ORDER BY id DESC LIMIT 1",
(incident_id,),
)
last_refresh = await cursor.fetchone()