All checks were successful
Deploy Development / deploy (push) Successful in 47s
Test Suite / pytest-backend (push) Successful in 42s
Test Suite / lint-backend (push) Successful in 2s
Test Suite / compose-smoke (push) Has been skipped
Test Suite / k6 /api/health Baseline (push) Successful in 18s
Test Suite / playwright-smoke (push) Successful in 12s
Co-authored-by: Cursor <cursoragent@cursor.com>
62 lines
2.3 KiB
Python
62 lines
2.3 KiB
Python
"""Actor workload read-models — tenant-scoped aggregation."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from psycopg2.extras import RealDictCursor
|
|
|
|
from db import get_connection
|
|
from tenant_context import TenantContext
|
|
|
|
|
|
def get_actor_workload(ctx: TenantContext) -> list[dict[str, Any]]:
|
|
"""Open/blocked/in_progress action counts per active actor in tenant."""
|
|
conn = get_connection()
|
|
try:
|
|
with conn.cursor(cursor_factory=RealDictCursor) as cur:
|
|
cur.execute(
|
|
"""
|
|
SELECT
|
|
a.id AS actor_id,
|
|
a.name AS display_name,
|
|
a.actor_type,
|
|
COUNT(*) FILTER (WHERE act.status = 'open') AS open_actions,
|
|
COUNT(*) FILTER (WHERE act.status = 'blocked') AS blocked_actions,
|
|
COUNT(*) FILTER (WHERE act.status = 'in_progress') AS in_progress_actions
|
|
FROM actors a
|
|
LEFT JOIN action_assignments aa
|
|
ON aa.actor_id = a.id AND aa.tenant_id = a.tenant_id
|
|
LEFT JOIN actions act
|
|
ON act.id = aa.action_id
|
|
AND act.tenant_id = aa.tenant_id
|
|
AND act.status IN ('open', 'in_progress', 'blocked')
|
|
WHERE a.tenant_id = %s AND a.is_active = TRUE
|
|
GROUP BY a.id, a.name, a.actor_type
|
|
ORDER BY
|
|
CASE a.actor_type
|
|
WHEN 'human' THEN 0
|
|
WHEN 'working_group' THEN 1
|
|
WHEN 'agent' THEN 2
|
|
ELSE 3
|
|
END,
|
|
a.name
|
|
""",
|
|
(ctx.tenant_id,),
|
|
)
|
|
result = []
|
|
for row in cur.fetchall():
|
|
result.append(
|
|
{
|
|
"actor_id": str(row["actor_id"]),
|
|
"display_name": row["display_name"],
|
|
"actor_type": row["actor_type"],
|
|
"open_actions": int(row["open_actions"] or 0),
|
|
"blocked_actions": int(row["blocked_actions"] or 0),
|
|
"in_progress_actions": int(row["in_progress_actions"] or 0),
|
|
}
|
|
)
|
|
return result
|
|
finally:
|
|
conn.close()
|