fix sandbox replace trace identity

This commit is contained in:
Azamat 2026-04-03 01:55:12 +03:00
parent dff28efecf
commit 02770bce7d
3 changed files with 120 additions and 7 deletions

View file

@ -9,7 +9,7 @@ from adapter.observability.noop import NoopMetrics, NoopTracer
from domain.sandbox import SandboxSession, SandboxStatus
from repository.sandbox_lock import ProcessLocalSandboxLifecycleLocker
from repository.sandbox_session import InMemorySandboxSessionRepository
from usecase.interface import AttrValue, Attrs
from usecase.interface import Attrs, AttrValue
from usecase.sandbox import CleanupExpiredSandboxes, CreateSandbox, CreateSandboxCommand
CHAT_ID = UUID('11111111-1111-1111-1111-111111111111')
@ -486,6 +486,10 @@ def test_create_sandbox_replace_records_observability_and_final_active_count(
'usecase.create_sandbox',
{'chat.id': str(CHAT_ID)},
{
'sandbox.previous_session.id': str(SESSION_OLD_ID),
'sandbox.previous_container.id': 'container-old',
'sandbox.new_session.id': str(SESSION_NEW_ID),
'sandbox.new_container.id': f'container-{SESSION_NEW_ID}',
'session.id': str(SESSION_NEW_ID),
'container.id': f'container-{SESSION_NEW_ID}',
'sandbox.result': 'replaced',
@ -649,6 +653,59 @@ def test_create_sandbox_error_records_observability(monkeypatch) -> None:
assert excinfo.value in span.errors
def test_create_sandbox_replace_stop_failure_preserves_separate_identities(
monkeypatch,
) -> None:
now = datetime(2026, 4, 2, 12, 0, tzinfo=UTC)
expired_session = SandboxSession(
session_id=SESSION_OLD_ID,
chat_id=CHAT_ID,
container_id='container-old',
status=SandboxStatus.RUNNING,
created_at=now - timedelta(minutes=10),
expires_at=now,
)
repository = InMemorySandboxSessionRepository()
repository.save(expired_session)
metrics = RecordingMetrics()
tracer = RecordingTracer()
usecase = CreateSandbox(
repository=repository,
locker=FakeLocker(),
runtime=FailingStopRuntime('container-old'),
clock=FakeClock(now),
logger=FakeLogger(),
metrics=metrics,
tracer=tracer,
ttl=timedelta(minutes=5),
)
monkeypatch.setattr('usecase.sandbox._new_session_id', lambda: SESSION_NEW_ID)
with pytest.raises(RuntimeError, match='stop_failed') as excinfo:
usecase.execute(CreateSandboxCommand(chat_id=CHAT_ID))
_assert_increment_metric_present(
metrics,
'sandbox.create.total',
attrs={'result': 'error'},
)
span = _find_span(
tracer,
'usecase.create_sandbox',
{'chat.id': str(CHAT_ID)},
{
'sandbox.previous_session.id': str(SESSION_OLD_ID),
'sandbox.previous_container.id': 'container-old',
'sandbox.new_session.id': str(SESSION_NEW_ID),
'sandbox.result': 'error',
},
)
assert 'sandbox.new_container.id' not in span.attrs
assert 'session.id' not in span.attrs
assert 'container.id' not in span.attrs
assert excinfo.value in span.errors
def test_create_sandbox_serializes_duplicate_concurrent_create_for_chat_id(
monkeypatch,
) -> None: