Orchestrator: eigener Worker pro Organisation (parallele Lanes)
Ersetzt die globale Warteschlange mit einem einzelnen Worker durch Per-Tenant-Lanes: jede Organisation bekommt eine eigene Queue und einen eigenen Worker-Task, die unabhaengig und parallel laufen. Lanes werden lazy angelegt und bei Leerlauf (60s) wieder beendet. - Skalarer Zustand (_current_task, _cancel_event) -> Maps pro incident_id (_current_tasks, _cancel_events); _queued_ids/_cancel_requested bleiben global (IDs sind lane-uebergreifend eindeutig). - enqueue_refresh/cancel_refresh: Signatur unveraendert, routen intern per tenant_id in die passende Lane. Oeffentliche Lagen (tenant_id NULL) in fester PUBLIC_LANE. - Optionales Ventil ORCHESTRATOR_MAX_PARALLEL (Default 0 = unbegrenzt) begrenzt bei Bedarf gleichzeitige Recherchen ueber alle Lanes. - /refreshing-Endpoint auf _current_tasks-Map umgestellt, Response-Format unveraendert (pro Tenant laeuft weiterhin hoechstens eine Lage). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -165,28 +165,25 @@ async def get_refreshing_incidents(
|
||||
)
|
||||
rows = await cursor.fetchall()
|
||||
|
||||
# Also include queued incidents from orchestrator
|
||||
# Queued- und laufende Lagen aus dem Orchestrator ergaenzen.
|
||||
from agents.orchestrator import orchestrator
|
||||
queued_ids = list(orchestrator._queued_ids) if hasattr(orchestrator, '_queued_ids') else []
|
||||
current_task = orchestrator._current_task if hasattr(orchestrator, '_current_task') else None
|
||||
# Session-Start des aktuell laufenden Tasks — stabil ueber Multi-Pass/Retry hinweg.
|
||||
# Verhindert, dass der Frontend-Timer beim Reload auf den letzten Log-Eintrag
|
||||
# (pass 2/3 oder retry n) zurueckspringt.
|
||||
current_started_at = (
|
||||
orchestrator._current_task_started_at
|
||||
if hasattr(orchestrator, '_current_task_started_at') else None
|
||||
)
|
||||
queued_ids = list(getattr(orchestrator, '_queued_ids', set()))
|
||||
# incident_id -> stabiler Session-Start (ueber Multi-Pass/Retry hinweg). Ersetzt
|
||||
# den frueheren Einzelwert, da jetzt mehrere Organisationen parallel laufen.
|
||||
current_tasks = getattr(orchestrator, '_current_tasks', {}) or {}
|
||||
|
||||
details = {}
|
||||
for row in rows:
|
||||
iid = row["incident_id"]
|
||||
started_at = (
|
||||
current_started_at
|
||||
if (iid == current_task and current_started_at)
|
||||
else row["started_at"]
|
||||
)
|
||||
session_start = current_tasks.get(iid)
|
||||
started_at = session_start if session_start else row["started_at"]
|
||||
details[str(iid)] = {"started_at": started_at}
|
||||
|
||||
# Pro Organisation laeuft hoechstens eine Lage gleichzeitig; der Endpoint ist
|
||||
# ohnehin tenant-gefiltert, daher genuegt der erste laufende Treffer.
|
||||
running_here = [row["incident_id"] for row in rows if row["incident_id"] in current_tasks]
|
||||
current_task = running_here[0] if running_here else None
|
||||
|
||||
return {
|
||||
"refreshing": [row["incident_id"] for row in rows],
|
||||
"queued": queued_ids,
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren