Merge branch 'master' into feature/q0-min-coverage
CI / lint (pull_request) Successful in 13s
CI / typecheck (pull_request) Successful in 28s
CI / quality (pull_request) Successful in 16s
CI / security (pull_request) Successful in 29s
CI / integration_tests (pull_request) Successful in 5m22s
CI / build (pull_request) Successful in 16s
CI / unit_tests (pull_request) Successful in 15m25s
CI / coverage (pull_request) Successful in 8m26s
CI / docker (pull_request) Successful in 40s
CI / lint (pull_request) Successful in 13s
CI / typecheck (pull_request) Successful in 28s
CI / quality (pull_request) Successful in 16s
CI / security (pull_request) Successful in 29s
CI / integration_tests (pull_request) Successful in 5m22s
CI / build (pull_request) Successful in 16s
CI / unit_tests (pull_request) Successful in 15m25s
CI / coverage (pull_request) Successful in 8m26s
CI / docker (pull_request) Successful in 40s
# Conflicts: # benchmarks/cli_format_bench.py # benchmarks/plan_phase_migration_bench.py # benchmarks/project_migration_bench.py # benchmarks/resource_registry_migration_bench.py # benchmarks/uow_lifecycle_bench.py
This commit is contained in:
@@ -8,6 +8,7 @@ Measures:
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import threading
|
||||||
from datetime import UTC, datetime
|
from datetime import UTC, datetime
|
||||||
|
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
@@ -19,6 +20,18 @@ from cleveragents.infrastructure.database.models import (
|
|||||||
LifecyclePlanModel,
|
LifecyclePlanModel,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Thread-safe counter so repeated ASV iterations never collide on IDs.
|
||||||
|
_iter_lock = threading.Lock()
|
||||||
|
_iter_counter = 0
|
||||||
|
|
||||||
|
|
||||||
|
def _next_iter() -> int:
|
||||||
|
"""Return a monotonically increasing iteration number."""
|
||||||
|
global _iter_counter
|
||||||
|
with _iter_lock:
|
||||||
|
_iter_counter += 1
|
||||||
|
return _iter_counter
|
||||||
|
|
||||||
|
|
||||||
def _now_iso() -> str:
|
def _now_iso() -> str:
|
||||||
return datetime.now(tz=UTC).isoformat()
|
return datetime.now(tz=UTC).isoformat()
|
||||||
@@ -41,7 +54,6 @@ class PlanInsertActionPhase:
|
|||||||
"""Benchmark inserting plans with phase='action' (new phase)."""
|
"""Benchmark inserting plans with phase='action' (new phase)."""
|
||||||
|
|
||||||
def setup(self) -> None:
|
def setup(self) -> None:
|
||||||
self._batch = 0
|
|
||||||
self.engine = create_engine("sqlite:///:memory:")
|
self.engine = create_engine("sqlite:///:memory:")
|
||||||
Base.metadata.create_all(self.engine)
|
Base.metadata.create_all(self.engine)
|
||||||
self.session_factory = sessionmaker(bind=self.engine)
|
self.session_factory = sessionmaker(bind=self.engine)
|
||||||
@@ -68,19 +80,19 @@ class PlanInsertActionPhase:
|
|||||||
self.engine.dispose()
|
self.engine.dispose()
|
||||||
|
|
||||||
def time_insert_100_action_phase_plans(self) -> None:
|
def time_insert_100_action_phase_plans(self) -> None:
|
||||||
offset = self._batch * 100
|
it = _next_iter()
|
||||||
self._batch += 1
|
base = it * 10000
|
||||||
session = self.session_factory()
|
session = self.session_factory()
|
||||||
now = _now_iso()
|
now = _now_iso()
|
||||||
for i in range(100):
|
for i in range(100):
|
||||||
plan = LifecyclePlanModel()
|
plan = LifecyclePlanModel()
|
||||||
plan.plan_id = _make_ulid(offset + i)
|
plan.plan_id = _make_ulid(base + i)
|
||||||
plan.action_name = "bench/phase-action"
|
plan.action_name = "bench/phase-action"
|
||||||
plan.namespaced_name = f"bench/plan-{offset + i}"
|
plan.namespaced_name = f"bench/plan-{it}-{i}"
|
||||||
plan.namespace = "bench"
|
plan.namespace = "bench"
|
||||||
plan.phase = "action"
|
plan.phase = "action"
|
||||||
plan.processing_state = "queued"
|
plan.processing_state = "queued"
|
||||||
plan.description = f"Benchmark plan {offset + i}"
|
plan.description = f"Benchmark plan {it}-{i}"
|
||||||
plan.tags_json = "[]"
|
plan.tags_json = "[]"
|
||||||
plan.created_at = now
|
plan.created_at = now
|
||||||
plan.updated_at = now
|
plan.updated_at = now
|
||||||
@@ -93,8 +105,6 @@ class PlanInsertApplyTerminalStates:
|
|||||||
"""Benchmark inserting plans with Apply terminal states."""
|
"""Benchmark inserting plans with Apply terminal states."""
|
||||||
|
|
||||||
def setup(self) -> None:
|
def setup(self) -> None:
|
||||||
self._applied_batch = 0
|
|
||||||
self._constrained_batch = 0
|
|
||||||
self.engine = create_engine("sqlite:///:memory:")
|
self.engine = create_engine("sqlite:///:memory:")
|
||||||
Base.metadata.create_all(self.engine)
|
Base.metadata.create_all(self.engine)
|
||||||
self.session_factory = sessionmaker(bind=self.engine)
|
self.session_factory = sessionmaker(bind=self.engine)
|
||||||
@@ -120,20 +130,19 @@ class PlanInsertApplyTerminalStates:
|
|||||||
self.engine.dispose()
|
self.engine.dispose()
|
||||||
|
|
||||||
def time_insert_50_applied_plans(self) -> None:
|
def time_insert_50_applied_plans(self) -> None:
|
||||||
offset = self._applied_batch * 50
|
it = _next_iter()
|
||||||
self._applied_batch += 1
|
base = it * 10000
|
||||||
session = self.session_factory()
|
session = self.session_factory()
|
||||||
now = _now_iso()
|
now = _now_iso()
|
||||||
for i in range(50):
|
for i in range(50):
|
||||||
uid = offset + i
|
|
||||||
plan = LifecyclePlanModel()
|
plan = LifecyclePlanModel()
|
||||||
plan.plan_id = _make_ulid(100_000 + uid)
|
plan.plan_id = _make_ulid(base + i)
|
||||||
plan.action_name = "bench/terminal-action"
|
plan.action_name = "bench/terminal-action"
|
||||||
plan.namespaced_name = f"bench/applied-{uid}"
|
plan.namespaced_name = f"bench/applied-{it}-{i}"
|
||||||
plan.namespace = "bench"
|
plan.namespace = "bench"
|
||||||
plan.phase = "apply"
|
plan.phase = "apply"
|
||||||
plan.processing_state = "applied"
|
plan.processing_state = "applied"
|
||||||
plan.description = f"Applied plan {uid}"
|
plan.description = f"Applied plan {it}-{i}"
|
||||||
plan.tags_json = "[]"
|
plan.tags_json = "[]"
|
||||||
plan.created_at = now
|
plan.created_at = now
|
||||||
plan.updated_at = now
|
plan.updated_at = now
|
||||||
@@ -142,20 +151,19 @@ class PlanInsertApplyTerminalStates:
|
|||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
def time_insert_50_constrained_plans(self) -> None:
|
def time_insert_50_constrained_plans(self) -> None:
|
||||||
offset = self._constrained_batch * 50
|
it = _next_iter()
|
||||||
self._constrained_batch += 1
|
base = it * 10000
|
||||||
session = self.session_factory()
|
session = self.session_factory()
|
||||||
now = _now_iso()
|
now = _now_iso()
|
||||||
for i in range(50):
|
for i in range(50):
|
||||||
uid = offset + i
|
|
||||||
plan = LifecyclePlanModel()
|
plan = LifecyclePlanModel()
|
||||||
plan.plan_id = _make_ulid(200_000 + uid)
|
plan.plan_id = _make_ulid(base + i)
|
||||||
plan.action_name = "bench/terminal-action"
|
plan.action_name = "bench/terminal-action"
|
||||||
plan.namespaced_name = f"bench/constrained-{uid}"
|
plan.namespaced_name = f"bench/constrained-{it}-{i}"
|
||||||
plan.namespace = "bench"
|
plan.namespace = "bench"
|
||||||
plan.phase = "apply"
|
plan.phase = "apply"
|
||||||
plan.processing_state = "constrained"
|
plan.processing_state = "constrained"
|
||||||
plan.description = f"Constrained plan {uid}"
|
plan.description = f"Constrained plan {it}-{i}"
|
||||||
plan.tags_json = "[]"
|
plan.tags_json = "[]"
|
||||||
plan.created_at = now
|
plan.created_at = now
|
||||||
plan.updated_at = now
|
plan.updated_at = now
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ Measures:
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import threading
|
||||||
from datetime import UTC, datetime
|
from datetime import UTC, datetime
|
||||||
|
|
||||||
from sqlalchemy import create_engine, event, text
|
from sqlalchemy import create_engine, event, text
|
||||||
@@ -23,6 +24,18 @@ from cleveragents.infrastructure.database.models import (
|
|||||||
ResourceTypeModel,
|
ResourceTypeModel,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Thread-safe counter so repeated ASV iterations never collide on names/IDs.
|
||||||
|
_iter_lock = threading.Lock()
|
||||||
|
_iter_counter = 0
|
||||||
|
|
||||||
|
|
||||||
|
def _next_iter() -> int:
|
||||||
|
"""Return a monotonically increasing iteration number."""
|
||||||
|
global _iter_counter
|
||||||
|
with _iter_lock:
|
||||||
|
_iter_counter += 1
|
||||||
|
return _iter_counter
|
||||||
|
|
||||||
|
|
||||||
def _now_iso() -> str:
|
def _now_iso() -> str:
|
||||||
return datetime.now(tz=UTC).isoformat()
|
return datetime.now(tz=UTC).isoformat()
|
||||||
@@ -42,8 +55,6 @@ class ProjectInsert:
|
|||||||
"""Benchmark inserting project records."""
|
"""Benchmark inserting project records."""
|
||||||
|
|
||||||
def setup(self) -> None:
|
def setup(self) -> None:
|
||||||
self._single_ctr = 0
|
|
||||||
self._batch_ctr = 0
|
|
||||||
self.engine = create_engine("sqlite:///:memory:")
|
self.engine = create_engine("sqlite:///:memory:")
|
||||||
event.listen(self.engine, "connect", _set_sqlite_pragma)
|
event.listen(self.engine, "connect", _set_sqlite_pragma)
|
||||||
with self.engine.connect() as conn:
|
with self.engine.connect() as conn:
|
||||||
@@ -56,10 +67,10 @@ class ProjectInsert:
|
|||||||
self.engine.dispose()
|
self.engine.dispose()
|
||||||
|
|
||||||
def time_insert_single_project(self) -> None:
|
def time_insert_single_project(self) -> None:
|
||||||
self._single_ctr += 1
|
it = _next_iter()
|
||||||
session = self.session_factory()
|
session = self.session_factory()
|
||||||
proj = NamespacedProjectModel(
|
proj = NamespacedProjectModel(
|
||||||
namespaced_name=f"bench/single-project-{self._single_ctr}",
|
namespaced_name=f"bench/single-project-{it}",
|
||||||
namespace="bench",
|
namespace="bench",
|
||||||
tags_json="[]",
|
tags_json="[]",
|
||||||
created_at=_now_iso(),
|
created_at=_now_iso(),
|
||||||
@@ -70,16 +81,14 @@ class ProjectInsert:
|
|||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
def time_insert_100_projects(self) -> None:
|
def time_insert_100_projects(self) -> None:
|
||||||
offset = self._batch_ctr * 100
|
it = _next_iter()
|
||||||
self._batch_ctr += 1
|
|
||||||
session = self.session_factory()
|
session = self.session_factory()
|
||||||
for i in range(100):
|
for i in range(100):
|
||||||
uid = offset + i
|
|
||||||
proj = NamespacedProjectModel(
|
proj = NamespacedProjectModel(
|
||||||
namespaced_name=f"bench/project-{uid}",
|
namespaced_name=f"bench/project-{it}-{i}",
|
||||||
namespace="bench",
|
namespace="bench",
|
||||||
description=f"Project {uid}",
|
description=f"Project {it}-{i}",
|
||||||
tags_json=json.dumps([f"tag-{uid}"]),
|
tags_json=json.dumps([f"tag-{it}-{i}"]),
|
||||||
created_at=_now_iso(),
|
created_at=_now_iso(),
|
||||||
updated_at=_now_iso(),
|
updated_at=_now_iso(),
|
||||||
)
|
)
|
||||||
@@ -92,7 +101,6 @@ class ProjectLinkInsert:
|
|||||||
"""Benchmark inserting project resource link records."""
|
"""Benchmark inserting project resource link records."""
|
||||||
|
|
||||||
def setup(self) -> None:
|
def setup(self) -> None:
|
||||||
self._batch_ctr = 0
|
|
||||||
self.engine = create_engine("sqlite:///:memory:")
|
self.engine = create_engine("sqlite:///:memory:")
|
||||||
event.listen(self.engine, "connect", _set_sqlite_pragma)
|
event.listen(self.engine, "connect", _set_sqlite_pragma)
|
||||||
with self.engine.connect() as conn:
|
with self.engine.connect() as conn:
|
||||||
@@ -112,18 +120,8 @@ class ProjectLinkInsert:
|
|||||||
rt.updated_at = _now_iso()
|
rt.updated_at = _now_iso()
|
||||||
session.add(rt)
|
session.add(rt)
|
||||||
|
|
||||||
# Create project
|
# Create resources (shared pool for link targets)
|
||||||
proj = NamespacedProjectModel(
|
for i in range(50):
|
||||||
namespaced_name="bench/link-project",
|
|
||||||
namespace="bench",
|
|
||||||
tags_json="[]",
|
|
||||||
created_at=_now_iso(),
|
|
||||||
updated_at=_now_iso(),
|
|
||||||
)
|
|
||||||
session.add(proj)
|
|
||||||
|
|
||||||
# Create resources (large pool so repeated iterations can use unique ones)
|
|
||||||
for i in range(5000):
|
|
||||||
r = ResourceModel()
|
r = ResourceModel()
|
||||||
r.resource_id = _make_ulid(i)
|
r.resource_id = _make_ulid(i)
|
||||||
r.type_name = "bench/git-checkout"
|
r.type_name = "bench/git-checkout"
|
||||||
@@ -139,15 +137,26 @@ class ProjectLinkInsert:
|
|||||||
self.engine.dispose()
|
self.engine.dispose()
|
||||||
|
|
||||||
def time_insert_50_links(self) -> None:
|
def time_insert_50_links(self) -> None:
|
||||||
offset = self._batch_ctr * 50
|
it = _next_iter()
|
||||||
self._batch_ctr += 1
|
base = it * 10000
|
||||||
session = self.session_factory()
|
session = self.session_factory()
|
||||||
|
# Create a unique project per iteration so the composite UNIQUE
|
||||||
|
# constraint (project_name, resource_id) never collides.
|
||||||
|
proj_name = f"bench/link-project-{it}"
|
||||||
|
proj = NamespacedProjectModel(
|
||||||
|
namespaced_name=proj_name,
|
||||||
|
namespace="bench",
|
||||||
|
tags_json="[]",
|
||||||
|
created_at=_now_iso(),
|
||||||
|
updated_at=_now_iso(),
|
||||||
|
)
|
||||||
|
session.add(proj)
|
||||||
|
session.flush()
|
||||||
for i in range(50):
|
for i in range(50):
|
||||||
uid = offset + i
|
|
||||||
link = ProjectResourceLinkModel(
|
link = ProjectResourceLinkModel(
|
||||||
link_id=_make_ulid(10_000 + uid),
|
link_id=_make_ulid(base + i),
|
||||||
project_name="bench/link-project",
|
project_name=proj_name,
|
||||||
resource_id=_make_ulid(uid),
|
resource_id=_make_ulid(i),
|
||||||
read_only=i % 2 == 0,
|
read_only=i % 2 == 0,
|
||||||
created_at=_now_iso(),
|
created_at=_now_iso(),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -45,20 +45,19 @@ class ResourceTypeInsert:
|
|||||||
"""Benchmark inserting resource type records."""
|
"""Benchmark inserting resource type records."""
|
||||||
|
|
||||||
def setup(self) -> None:
|
def setup(self) -> None:
|
||||||
self._single_ctr = 0
|
|
||||||
self._batch_ctr = 0
|
|
||||||
self.engine = create_engine("sqlite:///:memory:")
|
self.engine = create_engine("sqlite:///:memory:")
|
||||||
Base.metadata.create_all(self.engine)
|
Base.metadata.create_all(self.engine)
|
||||||
self.session_factory = sessionmaker(bind=self.engine)
|
self.session_factory = sessionmaker(bind=self.engine)
|
||||||
|
self._iter = 0
|
||||||
|
|
||||||
def teardown(self) -> None:
|
def teardown(self) -> None:
|
||||||
self.engine.dispose()
|
self.engine.dispose()
|
||||||
|
|
||||||
def time_insert_single_resource_type(self) -> None:
|
def time_insert_single_resource_type(self) -> None:
|
||||||
self._single_ctr += 1
|
self._iter += 1
|
||||||
session = self.session_factory()
|
session = self.session_factory()
|
||||||
rt = ResourceTypeModel()
|
rt = ResourceTypeModel()
|
||||||
rt.name = f"bench/type-single-{self._single_ctr}"
|
rt.name = f"bench/type-single-{self._iter}"
|
||||||
rt.namespace = "bench"
|
rt.namespace = "bench"
|
||||||
rt.resource_kind = "physical"
|
rt.resource_kind = "physical"
|
||||||
rt.user_addable = True
|
rt.user_addable = True
|
||||||
@@ -69,17 +68,16 @@ class ResourceTypeInsert:
|
|||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
def time_insert_100_resource_types(self) -> None:
|
def time_insert_100_resource_types(self) -> None:
|
||||||
offset = self._batch_ctr * 100
|
self._iter += 1
|
||||||
self._batch_ctr += 1
|
batch = self._iter
|
||||||
session = self.session_factory()
|
session = self.session_factory()
|
||||||
for i in range(100):
|
for i in range(100):
|
||||||
uid = offset + i
|
|
||||||
rt = ResourceTypeModel()
|
rt = ResourceTypeModel()
|
||||||
rt.name = f"bench/type-{uid}"
|
rt.name = f"bench/type-{batch}-{i}"
|
||||||
rt.namespace = "bench"
|
rt.namespace = "bench"
|
||||||
rt.resource_kind = "physical" if i % 2 == 0 else "virtual"
|
rt.resource_kind = "physical" if i % 2 == 0 else "virtual"
|
||||||
rt.user_addable = i % 3 == 0
|
rt.user_addable = i % 3 == 0
|
||||||
rt.args_schema_json = json.dumps([{"flag": f"--arg-{uid}"}])
|
rt.args_schema_json = json.dumps([{"flag": f"--arg-{batch}-{i}"}])
|
||||||
rt.created_at = _now_iso()
|
rt.created_at = _now_iso()
|
||||||
rt.updated_at = _now_iso()
|
rt.updated_at = _now_iso()
|
||||||
session.add(rt)
|
session.add(rt)
|
||||||
@@ -91,7 +89,6 @@ class ResourceInsert:
|
|||||||
"""Benchmark inserting resource records."""
|
"""Benchmark inserting resource records."""
|
||||||
|
|
||||||
def setup(self) -> None:
|
def setup(self) -> None:
|
||||||
self._batch_ctr = 0
|
|
||||||
self.engine = create_engine("sqlite:///:memory:")
|
self.engine = create_engine("sqlite:///:memory:")
|
||||||
Base.metadata.create_all(self.engine)
|
Base.metadata.create_all(self.engine)
|
||||||
self.session_factory = sessionmaker(bind=self.engine)
|
self.session_factory = sessionmaker(bind=self.engine)
|
||||||
@@ -106,24 +103,25 @@ class ResourceInsert:
|
|||||||
session.add(rt)
|
session.add(rt)
|
||||||
session.commit()
|
session.commit()
|
||||||
session.close()
|
session.close()
|
||||||
|
self._iter = 0
|
||||||
|
|
||||||
def teardown(self) -> None:
|
def teardown(self) -> None:
|
||||||
self.engine.dispose()
|
self.engine.dispose()
|
||||||
|
|
||||||
def time_insert_100_resources(self) -> None:
|
def time_insert_100_resources(self) -> None:
|
||||||
offset = self._batch_ctr * 100
|
self._iter += 1
|
||||||
self._batch_ctr += 1
|
batch = self._iter
|
||||||
session = self.session_factory()
|
session = self.session_factory()
|
||||||
for i in range(100):
|
for i in range(100):
|
||||||
uid = offset + i
|
idx = batch * 1000 + i
|
||||||
r = ResourceModel()
|
r = ResourceModel()
|
||||||
r.resource_id = _make_ulid(uid)
|
r.resource_id = _make_ulid(idx)
|
||||||
r.namespaced_name = f"bench/resource-{uid}"
|
r.namespaced_name = f"bench/resource-{batch}-{i}"
|
||||||
r.namespace = "bench"
|
r.namespace = "bench"
|
||||||
r.type_name = "bench/git-checkout"
|
r.type_name = "bench/git-checkout"
|
||||||
r.resource_kind = "physical"
|
r.resource_kind = "physical"
|
||||||
r.location = f"/path/to/resource-{uid}"
|
r.location = f"/path/to/resource-{idx}"
|
||||||
r.properties_json = json.dumps({"index": uid})
|
r.properties_json = json.dumps({"index": idx})
|
||||||
r.created_at = _now_iso()
|
r.created_at = _now_iso()
|
||||||
r.updated_at = _now_iso()
|
r.updated_at = _now_iso()
|
||||||
session.add(r)
|
session.add(r)
|
||||||
|
|||||||
@@ -67,11 +67,13 @@ def _make_bench_action(name: str = "local/bench-uow-action") -> Action:
|
|||||||
def _make_bench_plan(
|
def _make_bench_plan(
|
||||||
plan_id: str | None = None,
|
plan_id: str | None = None,
|
||||||
action_name: str = "local/bench-uow-action",
|
action_name: str = "local/bench-uow-action",
|
||||||
|
plan_name: str | None = None,
|
||||||
) -> V3Plan:
|
) -> V3Plan:
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
|
name = plan_name or f"bench-uow-plan-{_bench_ulid()}"
|
||||||
return V3Plan(
|
return V3Plan(
|
||||||
identity=PlanIdentity(plan_id=plan_id or _bench_ulid(), attempt=1),
|
identity=PlanIdentity(plan_id=plan_id or _bench_ulid(), attempt=1),
|
||||||
namespaced_name=NamespacedName(namespace="local", name="bench-uow-plan"),
|
namespaced_name=NamespacedName(namespace="local", name=name),
|
||||||
action_name=action_name,
|
action_name=action_name,
|
||||||
description="Bench plan",
|
description="Bench plan",
|
||||||
definition_of_done="Done",
|
definition_of_done="Done",
|
||||||
@@ -188,11 +190,22 @@ class TimeUowActionPlanRoundTrip:
|
|||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
def time_create_action_and_plan_via_uow(self) -> None:
|
def time_create_action_and_plan_via_uow(self) -> None:
|
||||||
# Reuse the pre-seeded action to avoid FK issues
|
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()
|
session = self.sf()
|
||||||
ctx = UnitOfWorkContext(session)
|
ctx = UnitOfWorkContext(session)
|
||||||
ctx.lifecycle_plans.create(
|
ctx.actions.create(_make_bench_action(action_name))
|
||||||
_make_bench_plan(action_name="local/bench-uow-action"),
|
session.commit()
|
||||||
)
|
session.close()
|
||||||
|
|
||||||
|
session = self.sf()
|
||||||
|
ctx = UnitOfWorkContext(session)
|
||||||
|
ctx.lifecycle_plans.create(_make_bench_plan(action_name=action_name))
|
||||||
session.commit()
|
session.commit()
|
||||||
session.close()
|
session.close()
|
||||||
|
|||||||
Reference in New Issue
Block a user