mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
fix(notifications): one duplicate-tolerant role lookup for every singleton-role site
The duplicate-CEO-row fix landed on one call site but three identical bare 'select(...).where(role == ...)' + scalar_one_or_none() lookups remained in the orchestrator (auditor + two CEO), each still raising MultipleResultsFound under the same condition. All five sites now route through a shared get_agent_by_role helper (earliest-created row wins). The five event-bus notification handlers also thread task_title so a revived producer renders titles instead of #id8 (protocol signatures updated to match the service), the pull_request CI trigger mirrors the push trigger's paths so a fork PR touching only those paths still runs CI, and a stale a2a comment about auditor/pr_reviewer lacking read_a2a is corrected.
This commit is contained in:
@@ -240,3 +240,49 @@ async def test_get_ceo_agent_tolerates_duplicate_ceo_rows(env: dict) -> None:
|
||||
# Does not raise, and pins to the earliest-created (never the later row).
|
||||
assert resolved is not None
|
||||
assert resolved.id != later_ceo.id
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_auditor_agent_tolerates_duplicate_auditor_rows(env: dict) -> None:
|
||||
"""Mirrors `test_get_ceo_agent_tolerates_duplicate_ceo_rows`: a second
|
||||
role=AUDITOR row must not make `_get_auditor_agent()` raise
|
||||
MultipleResultsFound — both now delegate to the shared
|
||||
`get_agent_by_role` helper."""
|
||||
db = env["db"]
|
||||
first_auditor = AgentTable(
|
||||
id=uuid4(),
|
||||
name="Auditor 1",
|
||||
slug=f"auditor-{uuid4().hex[:6]}",
|
||||
role=AgentRole.AUDITOR,
|
||||
team=None,
|
||||
status=AgentStatus.ACTIVE,
|
||||
model_config={},
|
||||
system_prompt="x",
|
||||
capabilities=[],
|
||||
permissions={},
|
||||
metrics={},
|
||||
)
|
||||
db.add(first_auditor)
|
||||
await db.flush()
|
||||
later_auditor = AgentTable(
|
||||
id=uuid4(),
|
||||
name="Auditor 2",
|
||||
slug=f"auditor-{uuid4().hex[:6]}",
|
||||
role=AgentRole.AUDITOR,
|
||||
team=None,
|
||||
status=AgentStatus.ACTIVE,
|
||||
model_config={},
|
||||
system_prompt="x",
|
||||
capabilities=[],
|
||||
permissions={},
|
||||
metrics={},
|
||||
created_at=datetime.now(UTC) + timedelta(hours=1),
|
||||
)
|
||||
db.add(later_auditor)
|
||||
await db.flush()
|
||||
|
||||
delivery = get_notification_delivery_service(db)
|
||||
resolved = await delivery._get_auditor_agent()
|
||||
|
||||
assert resolved is not None
|
||||
assert resolved.id != later_auditor.id
|
||||
|
||||
@@ -13,6 +13,7 @@ from roboco.models import AgentRole, AgentStatus, Team
|
||||
from roboco.services.repositories.query_helpers import (
|
||||
agent_id_filter,
|
||||
days_ago,
|
||||
get_agent_by_role,
|
||||
get_agent_by_slug,
|
||||
get_agent_slug,
|
||||
pagination,
|
||||
@@ -256,3 +257,48 @@ async def test_get_agent_by_slug(db_session: AsyncSession) -> None:
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_agent_by_slug_missing(db_session: AsyncSession) -> None:
|
||||
assert await get_agent_by_slug(db_session, "ghost-slug") is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_agent_by_role_tolerates_duplicate_rows(
|
||||
db_session: AsyncSession,
|
||||
) -> None:
|
||||
"""A second row of the same singleton role (a real hazard for CEO/AUDITOR
|
||||
in prod, and for the shared test DB here) must not raise
|
||||
MultipleResultsFound — the later-created duplicate is never selected."""
|
||||
earlier = AgentTable(
|
||||
id=uuid4(),
|
||||
name="Auditor Earlier",
|
||||
slug=f"qh-role-a-{uuid4().hex[:8]}",
|
||||
role=AgentRole.AUDITOR,
|
||||
team=None,
|
||||
status=AgentStatus.ACTIVE,
|
||||
model_config={},
|
||||
system_prompt="x",
|
||||
capabilities=[],
|
||||
permissions={},
|
||||
metrics={},
|
||||
)
|
||||
db_session.add(earlier)
|
||||
await db_session.flush()
|
||||
later = AgentTable(
|
||||
id=uuid4(),
|
||||
name="Auditor Later",
|
||||
slug=f"qh-role-b-{uuid4().hex[:8]}",
|
||||
role=AgentRole.AUDITOR,
|
||||
team=None,
|
||||
status=AgentStatus.ACTIVE,
|
||||
model_config={},
|
||||
system_prompt="x",
|
||||
capabilities=[],
|
||||
permissions={},
|
||||
metrics={},
|
||||
created_at=datetime.now(UTC) + timedelta(hours=1),
|
||||
)
|
||||
db_session.add(later)
|
||||
await db_session.flush()
|
||||
|
||||
resolved = await get_agent_by_role(db_session, AgentRole.AUDITOR)
|
||||
|
||||
assert resolved is not None
|
||||
assert resolved.id != later.id
|
||||
|
||||
Reference in New Issue
Block a user