fix(agents): budget runtime receipt readback queries
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 1m11s
CD Pipeline / build-and-deploy (push) Successful in 5m49s
CD Pipeline / post-deploy-checks (push) Has been cancelled

This commit is contained in:
ogt
2026-07-09 17:48:26 +08:00
parent f50acd45db
commit ce9f45b590
2 changed files with 135 additions and 1 deletions

View File

@@ -46,6 +46,8 @@ _LIVE_READBACK_SCHEMA_VERSION = "ai_agent_autonomous_runtime_receipt_readback_v1
_DEFAULT_PROJECT_ID = "awoooi"
_DEFAULT_LOOKBACK_HOURS = 24
_LIVE_RUNTIME_RECEIPT_TIMEOUT_SECONDS = 5.0
_RUNTIME_RECEIPT_QUERY_BUDGET_SECONDS = 4.0
_RUNTIME_RECEIPT_STATEMENT_TIMEOUT_MS = 900
_RUNTIME_RECEIPT_READBACK_CACHE_TTL_SECONDS = 20.0
# CD cancel-stale-cd no-op triggers must not change runtime payloads.
_EXECUTOR_OPERATION_TYPES = (
@@ -4113,16 +4115,42 @@ async def _load_ai_agent_autonomous_runtime_receipt_readback_uncached(
partial_query_failures: list[dict[str, str]] = []
try:
async with get_db_context(project_id) as db:
query_deadline = time.monotonic() + min(
_RUNTIME_RECEIPT_QUERY_BUDGET_SECONDS,
max(0.5, _LIVE_RUNTIME_RECEIPT_TIMEOUT_SECONDS - 0.75),
)
async def _set_statement_timeout() -> None:
await db.execute(text("SET LOCAL statement_timeout = '5000ms'"))
await db.execute(
text(
"SET LOCAL statement_timeout = "
f"'{int(_RUNTIME_RECEIPT_STATEMENT_TIMEOUT_MS)}ms'"
)
)
await _set_statement_timeout()
def _query_budget_exhausted(query_name: str) -> bool:
if time.monotonic() < query_deadline:
return False
partial_query_failures.append({
"query_name": query_name,
"error_type": "RuntimeReceiptQueryBudgetExceeded",
})
logger.warning(
"ai_agent_autonomous_runtime_trace_query_budget_exhausted",
project_id=project_id,
query_name=query_name,
)
return True
async def _safe_rows(
query_name: str,
sql: str,
fallback_sql: str | None = None,
) -> list[Mapping[str, Any]]:
if _query_budget_exhausted(query_name):
return []
try:
return (await db.execute(text(sql), params)).mappings().all()
except Exception as exc: # pragma: no cover - depends on live schema drift
@@ -4149,6 +4177,8 @@ async def _load_ai_agent_autonomous_runtime_receipt_readback_uncached(
error_type=type(reset_exc).__name__,
)
if fallback_sql:
if _query_budget_exhausted(f"{query_name}_fallback"):
return []
try:
return (await db.execute(text(fallback_sql), params)).mappings().all()
except Exception as fallback_exc: # pragma: no cover - live schema drift