forked from HAL9000/cleveragents-core
a0c6ecd3ad
Introduced a module-level flag _audit_subscriber_initialized to track whether audit_event_subscriber() has been successfully called. When get_container() is invoked and the flag is False, the subscriber initialization is reattempted regardless of whether _container already exists. On success the flag is set to True so no further attempts are made; on failure the warning is logged and the flag remains False so the next get_container() call retries. Previously, a failed audit subscriber init during the first get_container() call was permanently cached: _container was set but the subscriber was never retried. In CLI mode this is masked because each invocation is a new process, but in long-lived server processes the audit subscriber would remain unregistered for the process lifetime. Also brings in the TDD regression test from issue #1096 (branch tdd/m6-di-audit-cache-failure) with the @tdd_expected_fail tag removed, converting it to a normal passing regression guard. Added an ASV benchmark measuring retry-path performance. ISSUES CLOSED: #992 Reviewed-by: reviewer-pool-1 Closes #992 Co-authored-by: Brent E. Edwards <brent.edwards@cleverthis.com> Co-committed-by: Brent E. Edwards <brent.edwards@cleverthis.com>
72 lines
2.9 KiB
Python
72 lines
2.9 KiB
Python
"""Step definitions for tdd_di_audit_cache_failure.feature.
|
|
|
|
This test captures bug #992: ``get_container()`` cached a container even when
|
|
eager audit subscriber initialization failed during startup, and it did
|
|
not retry on subsequent ``get_container()`` calls.
|
|
|
|
Originally tagged ``@tdd_expected_fail`` so the expected assertion failure
|
|
(which proved the bug existed) was inverted to a CI pass until the fix for
|
|
#992 landed. After the fix, ``@tdd_expected_fail`` was removed and the test
|
|
now runs as a normal regression guard.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from behave import given, then, when
|
|
from behave.runner import Context
|
|
|
|
|
|
@given("g992- a container whose audit subscriber init fails once then succeeds")
|
|
def step_given_container_with_transient_audit_init_failure(context: Context) -> None:
|
|
"""Patch container factory so audit subscriber fails once, then succeeds."""
|
|
from cleveragents.application import container as container_module
|
|
|
|
class FakeContainer:
|
|
"""Minimal fake container to track audit subscriber initialization calls."""
|
|
|
|
def __init__(self) -> None:
|
|
self.audit_init_attempts: int = 0
|
|
|
|
def audit_event_subscriber(self) -> object:
|
|
"""Fail first call (simulating DB not ready), then succeed."""
|
|
self.audit_init_attempts += 1
|
|
if self.audit_init_attempts == 1:
|
|
raise RuntimeError("database not ready yet")
|
|
return object()
|
|
|
|
context.g992_original_container_class = container_module.Container
|
|
container_module.Container = FakeContainer # type: ignore[assignment]
|
|
|
|
def _cleanup() -> None:
|
|
container_module.Container = context.g992_original_container_class # type: ignore[assignment]
|
|
container_module.reset_container()
|
|
|
|
context.add_cleanup(_cleanup)
|
|
container_module.reset_container()
|
|
|
|
|
|
@when("g992- I call get_container twice")
|
|
def step_when_call_get_container_twice(context: Context) -> None:
|
|
"""Call get_container twice and keep references for assertions."""
|
|
from cleveragents.application.container import get_container
|
|
|
|
context.g992_first_container = get_container()
|
|
context.g992_second_container = get_container()
|
|
|
|
|
|
@then("g992- audit subscriber init should have been attempted twice")
|
|
def step_then_audit_subscriber_should_be_retried(context: Context) -> None:
|
|
"""Expect retry on second access after first initialization failure."""
|
|
first: Any = context.g992_first_container
|
|
second: Any = context.g992_second_container
|
|
assert first is second, "Expected get_container() to return a singleton instance"
|
|
|
|
attempts: int = getattr(first, "audit_init_attempts", 0)
|
|
assert attempts == 2, (
|
|
"Bug #992: get_container() did not retry audit subscriber initialization "
|
|
"after the first failure. Expected 2 attempts after two get_container() "
|
|
f"calls, but observed {attempts}."
|
|
)
|