fix(platform): bind AI runs to canonical correlation
Some checks failed
CD Pipeline / select-latest-carrier (push) Successful in 51s
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m45s
CD Pipeline / revalidate-deploy-carrier (push) Successful in 33s
CD Pipeline / revalidate-post-deploy-carrier (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled

This commit is contained in:
Your Name
2026-07-22 16:23:11 +08:00
parent 1cec67295b
commit 18b5ba25fa
13 changed files with 1051 additions and 105 deletions

View File

@@ -0,0 +1,162 @@
from __future__ import annotations
import asyncio
import os
from contextlib import asynccontextmanager
import pytest
from sqlalchemy import make_url, text
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
from sqlalchemy.pool import NullPool
from src.services import platform_runtime
_TEST_DATABASE_ENV = "AWOOOI_RUNTIME_IDENTITY_TEST_DATABASE_URL"
_TEST_DATABASE_NAME = "awoooi_runtime_identity_test"
_LOCAL_DATABASE_HOSTS = frozenset({"127.0.0.1", "localhost"})
def _validated_test_database_url() -> str:
raw_url = os.getenv(_TEST_DATABASE_ENV, "").strip()
if not raw_url:
pytest.skip(f"{_TEST_DATABASE_ENV} is required for the real PostgreSQL race test")
parsed = make_url(raw_url)
if (
parsed.get_backend_name() != "postgresql"
or parsed.get_driver_name() != "asyncpg"
or parsed.host not in _LOCAL_DATABASE_HOSTS
or parsed.database != _TEST_DATABASE_NAME
):
pytest.fail(
f"{_TEST_DATABASE_ENV} must use postgresql+asyncpg on localhost "
f"with database {_TEST_DATABASE_NAME!r}"
)
return raw_url
_RUN_STATE_DDL = """
CREATE TABLE awooop_run_state (
run_id UUID PRIMARY KEY,
project_id VARCHAR(64) NOT NULL,
agent_id VARCHAR(128) NOT NULL,
state VARCHAR(32) NOT NULL DEFAULT 'pending',
lease_until TIMESTAMP,
next_attempt_at TIMESTAMP,
heartbeat_at TIMESTAMP,
worker_id VARCHAR(128),
attempt_count SMALLINT NOT NULL DEFAULT 0,
max_attempts SMALLINT NOT NULL DEFAULT 3,
trace_id VARCHAR(128),
trigger_type VARCHAR(32),
trigger_ref VARCHAR(256),
is_shadow BOOLEAN NOT NULL DEFAULT TRUE,
input_sha256 VARCHAR(64),
output_sha256 VARCHAR(64),
cost_usd NUMERIC(10, 4) NOT NULL DEFAULT 0,
step_count SMALLINT NOT NULL DEFAULT 0,
error_code VARCHAR(64),
error_detail TEXT,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
started_at TIMESTAMP,
completed_at TIMESTAMP,
timeout_at TIMESTAMP
)
"""
_RUN_IDEMPOTENCY_DDL = """
CREATE TABLE awooop_run_idempotency (
idempotency_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
project_id VARCHAR(64) NOT NULL,
channel_type VARCHAR(32) NOT NULL,
provider_event_id VARCHAR(256) NOT NULL,
run_id UUID NOT NULL REFERENCES awooop_run_state(run_id),
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
CONSTRAINT uix_run_idempotency_key
UNIQUE (project_id, channel_type, provider_event_id)
)
"""
@pytest.mark.asyncio
async def test_concurrent_provider_event_has_one_postgresql_winner(
monkeypatch: pytest.MonkeyPatch,
) -> None:
engine = create_async_engine(_validated_test_database_url(), poolclass=NullPool)
factory = async_sessionmaker(engine, expire_on_commit=False, autoflush=False)
tables_created = False
@asynccontextmanager
async def test_db_context(project_id: str):
assert project_id == "awoooi"
async with factory() as session:
try:
yield session
await session.commit()
except Exception:
await session.rollback()
raise
async def skip_redis_cache(*_args: object) -> None:
return None
try:
async with engine.begin() as connection:
existing_tables = (
await connection.execute(
text(
"SELECT to_regclass('awooop_run_state'), "
"to_regclass('awooop_run_idempotency')"
)
)
).one()
if any(existing_tables):
pytest.fail(
"dedicated runtime identity test database must not contain "
"pre-existing run tables"
)
await connection.execute(text(_RUN_STATE_DDL))
await connection.execute(text(_RUN_IDEMPOTENCY_DDL))
tables_created = True
monkeypatch.setattr(platform_runtime, "get_db_context", test_db_context)
monkeypatch.setattr(platform_runtime, "_cache_idempotency", skip_redis_cache)
first, second = await asyncio.gather(
platform_runtime.create_run(
project_id="awoooi",
agent_id="runtime-agent",
trigger_type="channel_event",
channel_type="telegram",
provider_event_id="same-real-postgresql-event",
),
platform_runtime.create_run(
project_id="awoooi",
agent_id="runtime-agent",
trigger_type="channel_event",
channel_type="telegram",
provider_event_id="same-real-postgresql-event",
),
)
async with engine.connect() as connection:
run_count = await connection.scalar(
text("SELECT COUNT(*) FROM awooop_run_state")
)
mapping_count = await connection.scalar(
text("SELECT COUNT(*) FROM awooop_run_idempotency")
)
durable_run_id = await connection.scalar(
text("SELECT run_id FROM awooop_run_idempotency")
)
assert first[0] == second[0] == durable_run_id
assert sorted((first[1], second[1])) == [False, True]
assert run_count == 1
assert mapping_count == 1
finally:
if tables_created:
async with engine.begin() as connection:
await connection.execute(text("DROP TABLE awooop_run_idempotency"))
await connection.execute(text("DROP TABLE awooop_run_state"))
await engine.dispose()