c65e8a5285
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 16s
CI / lint (pull_request) Successful in 17s
CI / quality (pull_request) Successful in 29s
CI / typecheck (pull_request) Successful in 59s
CI / security (pull_request) Successful in 59s
CI / unit_tests (pull_request) Successful in 3m9s
CI / integration_tests (pull_request) Successful in 3m34s
CI / e2e_tests (pull_request) Successful in 3m54s
CI / docker (pull_request) Successful in 55s
CI / coverage (pull_request) Successful in 6m1s
CI / build (push) Successful in 15s
CI / lint (push) Successful in 16s
CI / quality (push) Successful in 27s
CI / typecheck (push) Successful in 38s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 48s
CI / unit_tests (push) Successful in 3m14s
CI / integration_tests (push) Successful in 3m30s
CI / docker (push) Successful in 56s
CI / e2e_tests (push) Successful in 4m43s
CI / coverage (push) Successful in 6m1s
CI / benchmark-publish (push) Successful in 19m50s
CI / benchmark-regression (pull_request) Successful in 37m17s
Implement cloud resource types (aws, gcp, azure) with credential fields, region/tenant metadata, and stubbed sandbox strategies. Credential resolution uses environment variables and profile names with no secrets logged. Key changes: - Add CloudResourceHandler with aws/gcp/azure type definitions - Add credential resolution from env vars and profile names - Add stubbed sandbox strategies (validate config, raise NotImplementedError) - Register cloud types in bootstrap_builtin_types - Credential masking via existing redaction patterns - Add Behave BDD tests, Robot integration tests, ASV benchmarks ISSUES CLOSED: #343
180 lines
5.9 KiB
Python
180 lines
5.9 KiB
Python
"""ASV benchmarks for database resource types and transaction sandbox.
|
|
|
|
Measures the performance of:
|
|
- Database type definition lookup
|
|
- Connection argument resolution
|
|
- Connection validation (SQLite)
|
|
- TransactionSandbox create/commit/rollback lifecycle
|
|
- SandboxFactory routing for transaction_rollback
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib
|
|
import os
|
|
import sqlite3
|
|
import sys
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
# Ensure the local *source* tree is importable even when ASV has an
|
|
# older build of the package installed.
|
|
_SRC = str(Path(__file__).resolve().parents[1] / "src")
|
|
if _SRC not in sys.path:
|
|
sys.path.insert(0, _SRC)
|
|
|
|
# Force-reload so ASV picks up the source tree version.
|
|
import cleveragents # noqa: E402
|
|
|
|
importlib.reload(cleveragents)
|
|
|
|
from cleveragents.infrastructure.sandbox.factory import ( # noqa: E402
|
|
SandboxFactory,
|
|
)
|
|
from cleveragents.infrastructure.sandbox.transaction_sandbox import ( # noqa: E402
|
|
TransactionSandbox,
|
|
)
|
|
from cleveragents.resource.handlers.database import ( # noqa: E402
|
|
DATABASE_TYPE_DEFS,
|
|
DatabaseResourceHandler,
|
|
resolve_connection_args,
|
|
validate_connection,
|
|
)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Type definition benchmarks
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TypeDefinitionSuite:
|
|
"""Benchmark database type definition operations."""
|
|
|
|
timeout = 60
|
|
|
|
def time_lookup_all_type_defs(self) -> None:
|
|
"""Time iterating all database type definitions."""
|
|
for td in DATABASE_TYPE_DEFS:
|
|
_ = td["name"]
|
|
|
|
def time_resolve_postgres_args(self) -> None:
|
|
"""Time resolving postgres connection args."""
|
|
resolve_connection_args(
|
|
{"host": "db.example.com", "port": 5432, "dbname": "mydb"},
|
|
"postgres",
|
|
)
|
|
|
|
def time_resolve_sqlite_args(self) -> None:
|
|
"""Time resolving sqlite connection args."""
|
|
resolve_connection_args({"path": "/tmp/test.db"}, "sqlite")
|
|
|
|
def time_handler_instantiation(self) -> None:
|
|
"""Time creating a DatabaseResourceHandler."""
|
|
DatabaseResourceHandler()
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Connection validation benchmarks
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class ConnectionValidationSuite:
|
|
"""Benchmark connection validation operations."""
|
|
|
|
timeout = 60
|
|
|
|
def setup(self) -> None:
|
|
"""Create a temp SQLite database for benchmarking."""
|
|
fd, self.db_path = tempfile.mkstemp(suffix=".db")
|
|
os.close(fd)
|
|
conn = sqlite3.connect(self.db_path)
|
|
conn.execute("CREATE TABLE bench (id INTEGER PRIMARY KEY)")
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def teardown(self) -> None:
|
|
"""Remove the temp database."""
|
|
if hasattr(self, "db_path") and os.path.exists(self.db_path):
|
|
os.unlink(self.db_path)
|
|
|
|
def time_validate_sqlite_file(self) -> None:
|
|
"""Time validating a file-based SQLite connection."""
|
|
validate_connection("sqlite", {"path": self.db_path})
|
|
|
|
def time_validate_sqlite_memory(self) -> None:
|
|
"""Time validating an in-memory SQLite connection."""
|
|
validate_connection("sqlite", {"path": ":memory:"})
|
|
|
|
def time_validate_postgres_stub(self) -> None:
|
|
"""Time validating a postgres stub (no driver)."""
|
|
validate_connection(
|
|
"postgres",
|
|
{"host": "localhost", "port": 5432, "dbname": "bench"},
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Transaction sandbox benchmarks
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TransactionSandboxSuite:
|
|
"""Benchmark TransactionSandbox lifecycle operations."""
|
|
|
|
timeout = 60
|
|
|
|
def setup(self) -> None:
|
|
"""Create a temp SQLite database for benchmarking."""
|
|
fd, self.db_path = tempfile.mkstemp(suffix=".db")
|
|
os.close(fd)
|
|
conn = sqlite3.connect(self.db_path)
|
|
conn.execute("CREATE TABLE bench (id INTEGER PRIMARY KEY, val TEXT)")
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def teardown(self) -> None:
|
|
"""Remove the temp database."""
|
|
if hasattr(self, "db_path") and os.path.exists(self.db_path):
|
|
os.unlink(self.db_path)
|
|
|
|
def time_create_and_cleanup(self) -> None:
|
|
"""Time sandbox create + cleanup cycle."""
|
|
sandbox = TransactionSandbox(resource_id="bench-1", original_path=self.db_path)
|
|
sandbox.create(plan_id="BENCH-PLAN")
|
|
sandbox.cleanup()
|
|
|
|
def time_create_insert_commit(self) -> None:
|
|
"""Time full sandbox lifecycle: create, insert, commit, cleanup."""
|
|
sandbox = TransactionSandbox(resource_id="bench-2", original_path=self.db_path)
|
|
sandbox.create(plan_id="BENCH-PLAN")
|
|
sandbox.execute("INSERT INTO bench (id, val) VALUES (1, 'bench')")
|
|
sandbox.commit("bench commit")
|
|
sandbox.cleanup()
|
|
|
|
def time_create_insert_rollback(self) -> None:
|
|
"""Time sandbox lifecycle with rollback."""
|
|
sandbox = TransactionSandbox(resource_id="bench-3", original_path=self.db_path)
|
|
sandbox.create(plan_id="BENCH-PLAN")
|
|
sandbox.execute("INSERT INTO bench (id, val) VALUES (2, 'rollback')")
|
|
sandbox.rollback()
|
|
sandbox.cleanup()
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Factory routing benchmarks
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class FactoryRoutingSuite:
|
|
"""Benchmark SandboxFactory routing for database strategies."""
|
|
|
|
timeout = 60
|
|
|
|
def time_factory_transaction_rollback(self) -> None:
|
|
"""Time factory creating a TransactionSandbox."""
|
|
factory = SandboxFactory()
|
|
factory.create_sandbox(
|
|
resource_id="bench-factory",
|
|
original_path=":memory:",
|
|
sandbox_strategy="transaction_rollback",
|
|
)
|