feat(cli): add resource commands (core)
CI / lint (pull_request) Successful in 15s
CI / typecheck (pull_request) Successful in 28s
CI / security (pull_request) Successful in 23s
CI / quality (pull_request) Successful in 15s
CI / integration_tests (pull_request) Successful in 5m11s
CI / build (pull_request) Successful in 16s
CI / unit_tests (pull_request) Successful in 14m31s
CI / docker (pull_request) Successful in 40s
CI / coverage (pull_request) Successful in 8m18s
CI / lint (push) Successful in 13s
CI / typecheck (push) Successful in 28s
CI / security (push) Successful in 23s
CI / quality (push) Successful in 16s
CI / integration_tests (push) Successful in 4m58s
CI / build (push) Successful in 15s
CI / unit_tests (push) Successful in 15m30s
CI / coverage (push) Has been cancelled
CI / docker (push) Has been cancelled
CI / lint (pull_request) Successful in 15s
CI / typecheck (pull_request) Successful in 28s
CI / security (pull_request) Successful in 23s
CI / quality (pull_request) Successful in 15s
CI / integration_tests (pull_request) Successful in 5m11s
CI / build (pull_request) Successful in 16s
CI / unit_tests (pull_request) Successful in 14m31s
CI / docker (pull_request) Successful in 40s
CI / coverage (pull_request) Successful in 8m18s
CI / lint (push) Successful in 13s
CI / typecheck (push) Successful in 28s
CI / security (push) Successful in 23s
CI / quality (push) Successful in 16s
CI / integration_tests (push) Successful in 4m58s
CI / build (push) Successful in 15s
CI / unit_tests (push) Successful in 15m30s
CI / coverage (push) Has been cancelled
CI / docker (push) Has been cancelled
This commit was merged in pull request #71.
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
"""ASV benchmarks for project repository operations.
|
||||
|
||||
Measures:
|
||||
- NamespacedProjectRepository create/get/list throughput
|
||||
- ProjectResourceLinkRepository create_link/list_links throughput
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import UTC, datetime
|
||||
|
||||
from sqlalchemy import create_engine, event, text
|
||||
from sqlalchemy.orm import Session, sessionmaker
|
||||
|
||||
from cleveragents.domain.models.core.project import NamespacedProject
|
||||
from cleveragents.infrastructure.database.models import (
|
||||
Base,
|
||||
ResourceModel,
|
||||
ResourceTypeModel,
|
||||
)
|
||||
from cleveragents.infrastructure.database.repositories import (
|
||||
NamespacedProjectRepository,
|
||||
ProjectResourceLinkRepository,
|
||||
)
|
||||
|
||||
|
||||
def _now_iso() -> str:
|
||||
return datetime.now(tz=UTC).isoformat()
|
||||
|
||||
|
||||
def _set_sqlite_pragma(dbapi_conn: object, _connection_record: object) -> None:
|
||||
cursor = dbapi_conn.cursor() # type: ignore[union-attr]
|
||||
cursor.execute("PRAGMA foreign_keys = ON")
|
||||
cursor.close()
|
||||
|
||||
|
||||
class ProjectRepositoryCRUD:
|
||||
"""Benchmark project repository CRUD operations."""
|
||||
|
||||
def setup(self) -> None:
|
||||
self.engine = create_engine("sqlite:///:memory:")
|
||||
event.listen(self.engine, "connect", _set_sqlite_pragma)
|
||||
with self.engine.connect() as conn:
|
||||
conn.execute(text("PRAGMA foreign_keys = ON"))
|
||||
conn.commit()
|
||||
Base.metadata.create_all(self.engine)
|
||||
self.sf = sessionmaker(bind=self.engine)
|
||||
|
||||
def teardown(self) -> None:
|
||||
self.engine.dispose()
|
||||
|
||||
def time_create_and_get_project(self) -> None:
|
||||
repo = NamespacedProjectRepository(session_factory=self.sf)
|
||||
session = self.sf()
|
||||
project = NamespacedProject(name="bench-proj", namespace="bench")
|
||||
repo.create(project)
|
||||
session.commit()
|
||||
repo.get("bench/bench-proj")
|
||||
repo.delete("bench/bench-proj")
|
||||
session.commit()
|
||||
|
||||
def time_list_50_projects(self) -> None:
|
||||
repo = NamespacedProjectRepository(session_factory=self.sf)
|
||||
session = self.sf()
|
||||
for i in range(50):
|
||||
repo.create(NamespacedProject(name=f"proj-{i}", namespace="bench"))
|
||||
session.commit()
|
||||
repo.list_projects(namespace="bench", limit=50)
|
||||
for i in range(50):
|
||||
repo.delete(f"bench/proj-{i}")
|
||||
session.commit()
|
||||
|
||||
|
||||
class LinkRepositoryCRUD:
|
||||
"""Benchmark link repository operations."""
|
||||
|
||||
def setup(self) -> None:
|
||||
self.engine = create_engine("sqlite:///:memory:")
|
||||
event.listen(self.engine, "connect", _set_sqlite_pragma)
|
||||
with self.engine.connect() as conn:
|
||||
conn.execute(text("PRAGMA foreign_keys = ON"))
|
||||
conn.commit()
|
||||
Base.metadata.create_all(self.engine)
|
||||
self.sf = sessionmaker(bind=self.engine)
|
||||
|
||||
session = self.sf()
|
||||
# Resource type
|
||||
rt = ResourceTypeModel()
|
||||
rt.name = "bench/git-checkout" # type: ignore[assignment]
|
||||
rt.namespace = "bench" # type: ignore[assignment]
|
||||
rt.resource_kind = "physical" # type: ignore[assignment]
|
||||
rt.user_addable = True # type: ignore[assignment]
|
||||
rt.created_at = _now_iso() # type: ignore[assignment]
|
||||
rt.updated_at = _now_iso() # type: ignore[assignment]
|
||||
session.add(rt)
|
||||
session.commit()
|
||||
|
||||
# Project
|
||||
project_repo = NamespacedProjectRepository(session_factory=self.sf)
|
||||
project_repo.create(NamespacedProject(name="link-bench", namespace="bench"))
|
||||
session.commit()
|
||||
|
||||
# Resources
|
||||
for i in range(30):
|
||||
r = ResourceModel()
|
||||
r.resource_id = str(i).zfill(26) # type: ignore[assignment]
|
||||
r.type_name = "bench/git-checkout" # type: ignore[assignment]
|
||||
r.resource_kind = "physical" # type: ignore[assignment]
|
||||
r.created_at = _now_iso() # type: ignore[assignment]
|
||||
r.updated_at = _now_iso() # type: ignore[assignment]
|
||||
session.add(r)
|
||||
session.commit()
|
||||
|
||||
def teardown(self) -> None:
|
||||
self.engine.dispose()
|
||||
|
||||
def time_create_and_list_30_links(self) -> None:
|
||||
link_repo = ProjectResourceLinkRepository(session_factory=self.sf)
|
||||
session = self.sf()
|
||||
link_ids: list[str] = []
|
||||
for i in range(30):
|
||||
link = link_repo.create_link(
|
||||
project_name="bench/link-bench",
|
||||
resource_id=str(i).zfill(26),
|
||||
)
|
||||
session.commit()
|
||||
link_ids.append(str(link.link_id))
|
||||
link_repo.list_links("bench/link-bench")
|
||||
for lid in link_ids:
|
||||
link_repo.remove_link(lid)
|
||||
session.commit()
|
||||
@@ -0,0 +1,103 @@
|
||||
"""ASV benchmarks for Resource CLI command parsing overhead.
|
||||
|
||||
Measures the import time and basic construction of resource CLI objects
|
||||
to track startup overhead.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
class ResourceCliImportBench:
|
||||
"""Benchmark resource CLI module import time."""
|
||||
|
||||
timeout = 30.0
|
||||
|
||||
def setup(self) -> None:
|
||||
"""Pre-warm Python import caches."""
|
||||
pass
|
||||
|
||||
def time_import_resource_module(self) -> None:
|
||||
"""Measure import time of the resource CLI module."""
|
||||
import importlib
|
||||
|
||||
import cleveragents.cli.commands.resource as mod
|
||||
|
||||
importlib.reload(mod)
|
||||
|
||||
def time_import_formatting_module(self) -> None:
|
||||
"""Measure import time of the formatting module."""
|
||||
import importlib
|
||||
|
||||
import cleveragents.cli.formatting as mod
|
||||
|
||||
importlib.reload(mod)
|
||||
|
||||
|
||||
class ResourceDictConversionBench:
|
||||
"""Benchmark resource dict conversion helpers."""
|
||||
|
||||
timeout = 30.0
|
||||
|
||||
def setup(self) -> None:
|
||||
"""Set up test data."""
|
||||
from datetime import UTC, datetime
|
||||
|
||||
self.mock_resource_data = {
|
||||
"resource_id": "01HXYZ1234567890ABCDEFGHIJ",
|
||||
"name": "local/bench-resource",
|
||||
"resource_type_name": "git-checkout",
|
||||
"classification": "physical",
|
||||
"description": "Benchmark test resource",
|
||||
"location": "/tmp/bench",
|
||||
"properties": {"path": "/tmp/bench", "branch": "main"},
|
||||
"created_at": datetime.now(tz=UTC),
|
||||
"updated_at": datetime.now(tz=UTC),
|
||||
}
|
||||
|
||||
def time_resource_dict_construction(self) -> None:
|
||||
"""Measure dict construction for resource output."""
|
||||
data = self.mock_resource_data
|
||||
result = {
|
||||
"resource_id": data["resource_id"],
|
||||
"name": data["name"],
|
||||
"type": data["resource_type_name"],
|
||||
"classification": str(data["classification"]),
|
||||
"description": data["description"],
|
||||
"location": data["location"],
|
||||
"properties": data["properties"],
|
||||
"created_at": data["created_at"].isoformat(),
|
||||
"updated_at": data["updated_at"].isoformat(),
|
||||
}
|
||||
assert result["name"] == "local/bench-resource"
|
||||
|
||||
|
||||
class ResourceTypeListBench:
|
||||
"""Benchmark resource type list operations."""
|
||||
|
||||
timeout = 60.0
|
||||
|
||||
def setup(self) -> None:
|
||||
"""Create an in-memory registry with bootstrapped types."""
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from cleveragents.application.services.resource_registry_service import (
|
||||
ResourceRegistryService,
|
||||
)
|
||||
from cleveragents.infrastructure.database.models import Base
|
||||
|
||||
engine = create_engine("sqlite:///:memory:", echo=False)
|
||||
Base.metadata.create_all(engine)
|
||||
factory = sessionmaker(bind=engine, expire_on_commit=False)
|
||||
self.service = ResourceRegistryService(session_factory=factory)
|
||||
self.service.bootstrap_builtin_types()
|
||||
|
||||
def time_list_types(self) -> None:
|
||||
"""Measure listing all resource types."""
|
||||
types = self.service.list_types()
|
||||
assert len(types) >= 2
|
||||
|
||||
def time_show_type(self) -> None:
|
||||
"""Measure showing a single resource type."""
|
||||
spec = self.service.show_type("git-checkout")
|
||||
assert spec.name == "git-checkout"
|
||||
@@ -0,0 +1,74 @@
|
||||
"""ASV benchmarks for ResourceRegistryService operations."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from cleveragents.application.services.resource_registry_service import (
|
||||
ResourceRegistryService,
|
||||
)
|
||||
from cleveragents.infrastructure.database.models import Base
|
||||
|
||||
|
||||
class BootstrapBenchmark:
|
||||
"""Benchmark built-in type bootstrap."""
|
||||
|
||||
timeout = 30.0
|
||||
|
||||
def setup(self) -> None:
|
||||
self.engine = create_engine("sqlite:///:memory:")
|
||||
Base.metadata.create_all(self.engine)
|
||||
self.factory = sessionmaker(bind=self.engine)
|
||||
|
||||
def time_bootstrap_builtin_types(self) -> None:
|
||||
svc = ResourceRegistryService(session_factory=self.factory)
|
||||
svc.bootstrap_builtin_types()
|
||||
|
||||
def time_bootstrap_idempotent(self) -> None:
|
||||
svc = ResourceRegistryService(session_factory=self.factory)
|
||||
svc.bootstrap_builtin_types()
|
||||
svc.bootstrap_builtin_types()
|
||||
|
||||
|
||||
class ListTypesBenchmark:
|
||||
"""Benchmark type listing operations."""
|
||||
|
||||
timeout = 30.0
|
||||
|
||||
def setup(self) -> None:
|
||||
self.engine = create_engine("sqlite:///:memory:")
|
||||
Base.metadata.create_all(self.engine)
|
||||
self.factory = sessionmaker(bind=self.engine)
|
||||
svc = ResourceRegistryService(session_factory=self.factory)
|
||||
svc.bootstrap_builtin_types()
|
||||
self.svc = svc
|
||||
|
||||
def time_list_all_types(self) -> None:
|
||||
self.svc.list_types()
|
||||
|
||||
def time_show_type(self) -> None:
|
||||
self.svc.show_type("git-checkout")
|
||||
|
||||
|
||||
class RegisterResourceBenchmark:
|
||||
"""Benchmark resource registration."""
|
||||
|
||||
timeout = 30.0
|
||||
|
||||
def setup(self) -> None:
|
||||
self.engine = create_engine("sqlite:///:memory:")
|
||||
Base.metadata.create_all(self.engine)
|
||||
self.factory = sessionmaker(bind=self.engine)
|
||||
svc = ResourceRegistryService(session_factory=self.factory)
|
||||
svc.bootstrap_builtin_types()
|
||||
self.svc = svc
|
||||
self.counter = 0
|
||||
|
||||
def time_register_resource(self) -> None:
|
||||
self.counter += 1
|
||||
self.svc.register_resource(
|
||||
type_name="git-checkout",
|
||||
name=f"local/bench-repo-{self.counter}",
|
||||
location="/tmp/bench",
|
||||
)
|
||||
Reference in New Issue
Block a user