"""ASV benchmarks for UnitOfWork lifecycle repository wiring. Measures overhead of creating UnitOfWorkContext and accessing actions / lifecycle_plans repositories. """ from __future__ import annotations from datetime import datetime from sqlalchemy import create_engine, event from sqlalchemy.orm import Session, sessionmaker from cleveragents.domain.models.core.action import Action, ActionState from cleveragents.domain.models.core.plan import ( NamespacedName, PlanIdentity, PlanPhase, PlanTimestamps, ProcessingState, ) from cleveragents.domain.models.core.plan import Plan as V3Plan from cleveragents.infrastructure.database.models import Base from cleveragents.infrastructure.database.unit_of_work import UnitOfWorkContext _CB32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ" _bench_counter = 5000 def _bench_ulid() -> str: global _bench_counter _bench_counter += 1 n = _bench_counter suffix = "" for _ in range(8): suffix = _CB32[n % 32] + suffix n //= 32 return f"01HGZ6FE0AQDYTR4BX{suffix}" def _make_bench_action(name: str = "local/bench-uow-action") -> Action: parts = name.split("/", 1) namespace = parts[0] if len(parts) == 2 else "local" short_name = parts[1] if len(parts) == 2 else parts[0] now = datetime.now() return Action( namespaced_name=NamespacedName(namespace=namespace, name=short_name), description=f"Bench action {short_name}", long_description=None, definition_of_done="Done", strategy_actor="local/s", execution_actor="local/e", estimation_actor=None, review_actor=None, arguments=[], reusable=True, read_only=False, state=ActionState("available"), created_at=now, updated_at=now, created_by=None, tags=[], ) def _make_bench_plan( plan_id: str | None = None, action_name: str = "local/bench-uow-action", plan_name: str | None = None, ) -> V3Plan: now = datetime.now() name = plan_name or f"bench-uow-plan-{_bench_ulid()}" return V3Plan( identity=PlanIdentity(plan_id=plan_id or _bench_ulid(), attempt=1), namespaced_name=NamespacedName(namespace="local", name=name), action_name=action_name, description="Bench plan", definition_of_done="Done", strategy_actor="local/s", execution_actor="local/e", phase=PlanPhase("action"), processing_state=ProcessingState("queued"), timestamps=PlanTimestamps(created_at=now, updated_at=now), project_links=[], arguments={}, arguments_order=[], invariants=[], reusable=True, read_only=False, created_by=None, tags=[], ) class TimeUowContextCreation: """Benchmark UnitOfWorkContext instantiation.""" timeout = 30.0 def setup(self) -> None: self.engine = create_engine( "sqlite:///:memory:", echo=False, future=True, connect_args={"check_same_thread": False}, ) @event.listens_for(self.engine, "connect") def _fk(dbapi_conn, _rec): # type: ignore[no-untyped-def] cursor = dbapi_conn.cursor() cursor.execute("PRAGMA foreign_keys=ON") cursor.close() Base.metadata.create_all(self.engine) self.sf: sessionmaker[Session] = sessionmaker( bind=self.engine, expire_on_commit=False, autoflush=False, autocommit=False, class_=Session, ) def time_create_context(self) -> None: session = self.sf() _ = UnitOfWorkContext(session) session.close() def time_access_actions_repo(self) -> None: session = self.sf() ctx = UnitOfWorkContext(session) _ = ctx.actions session.close() def time_access_lifecycle_plans_repo(self) -> None: session = self.sf() ctx = UnitOfWorkContext(session) _ = ctx.lifecycle_plans session.close() class TimeUowActionPlanRoundTrip: """Benchmark creating action + plan via UoW and retrieving.""" timeout = 30.0 def setup(self) -> None: self.engine = create_engine( "sqlite:///:memory:", echo=False, future=True, connect_args={"check_same_thread": False}, ) @event.listens_for(self.engine, "connect") def _fk(dbapi_conn, _rec): # type: ignore[no-untyped-def] cursor = dbapi_conn.cursor() cursor.execute("PRAGMA foreign_keys=ON") cursor.close() Base.metadata.create_all(self.engine) self.sf: sessionmaker[Session] = sessionmaker( bind=self.engine, expire_on_commit=False, autoflush=False, autocommit=False, class_=Session, ) # Seed an action for plan creation benchmarks session = self.sf() ctx = UnitOfWorkContext(session) ctx.actions.create(_make_bench_action("local/bench-uow-action")) session.commit() session.close() def time_create_action_via_uow(self) -> None: session = self.sf() ctx = UnitOfWorkContext(session) uid = _bench_ulid() ctx.actions.create(_make_bench_action(f"local/bench-action-{uid}")) session.commit() session.close() def time_create_plan_via_uow(self) -> None: session = self.sf() ctx = UnitOfWorkContext(session) ctx.lifecycle_plans.create(_make_bench_plan()) session.commit() session.close() def time_create_action_and_plan_via_uow(self) -> None: uid = _bench_ulid() # NamespacedName.validate_name lowercases the name, so the action # is stored with a lowercased namespaced_name PK. The plan's # action_name (a plain-string FK) must match exactly. action_name = f"local/bench-combo-{uid}".lower() # Commit the action first so the FK reference is durable before # the plan repository (which has its own retry/rollback logic) # attempts the insert. session = self.sf() ctx = UnitOfWorkContext(session) ctx.actions.create(_make_bench_action(action_name)) session.commit() session.close() session = self.sf() ctx = UnitOfWorkContext(session) ctx.lifecycle_plans.create(_make_bench_plan(action_name=action_name)) session.commit() session.close()