fix(perf): bound truth-chain quality reads
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 4m29s
CD Pipeline / build-and-deploy (push) Successful in 15m43s
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 1s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Successful in 18s
CD Pipeline / post-deploy-checks (push) Successful in 11m37s
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 4m29s
CD Pipeline / build-and-deploy (push) Successful in 15m43s
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 1s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Successful in 18s
CD Pipeline / post-deploy-checks (push) Successful in 11m37s
This commit is contained in:
@@ -41,6 +41,27 @@ _JSON_TEXT_FIELDS = {"gate_result", "source_envelope"}
|
||||
_QUALITY_SUMMARY_CACHE_TTL_SECONDS = int(
|
||||
os.getenv("AWOOOP_QUALITY_SUMMARY_CACHE_TTL_SECONDS", "120")
|
||||
)
|
||||
_QUALITY_SUMMARY_STATEMENT_TIMEOUT_MS = max(
|
||||
1_000,
|
||||
min(
|
||||
int(os.getenv("AWOOOP_QUALITY_SUMMARY_STATEMENT_TIMEOUT_MS", "12000")),
|
||||
30_000,
|
||||
),
|
||||
)
|
||||
_QUALITY_SUMMARY_MAX_BATCH_ROWS = max(
|
||||
_MAX_ROWS,
|
||||
min(
|
||||
int(os.getenv("AWOOOP_QUALITY_SUMMARY_MAX_BATCH_ROWS", "5000")),
|
||||
10_000,
|
||||
),
|
||||
)
|
||||
_TRUTH_CHAIN_BRANCH_ROWS_PER_INCIDENT = max(
|
||||
5,
|
||||
min(
|
||||
int(os.getenv("AWOOOP_TRUTH_CHAIN_BRANCH_ROWS_PER_INCIDENT", "20")),
|
||||
_MAX_ROWS,
|
||||
),
|
||||
)
|
||||
_QUALITY_SUMMARY_OBSERVATIONS: dict[str, dict[str, Any]] = {}
|
||||
|
||||
|
||||
@@ -235,6 +256,260 @@ async def _fetch_inbound_conversation_event_rows(
|
||||
)[:limit]
|
||||
|
||||
|
||||
def _truth_chain_branch_limit(source_ids: list[str], limit: int) -> int:
|
||||
return max(
|
||||
1,
|
||||
min(
|
||||
int(limit),
|
||||
_QUALITY_SUMMARY_MAX_BATCH_ROWS,
|
||||
len(source_ids) * _TRUTH_CHAIN_BRANCH_ROWS_PER_INCIDENT,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def _fetch_automation_operation_rows_for_incidents(
|
||||
db: Any,
|
||||
*,
|
||||
incident_ids: list[str],
|
||||
limit: int,
|
||||
cutoff: datetime | None = None,
|
||||
allow_text_fallback: bool = False,
|
||||
) -> list[dict[str, Any]]:
|
||||
"""Fetch operation rows through direct, indexable incident references."""
|
||||
source_ids = list(dict.fromkeys(str(value) for value in incident_ids if value))
|
||||
if not source_ids:
|
||||
return []
|
||||
|
||||
columns = """
|
||||
op_id,
|
||||
operation_type,
|
||||
status,
|
||||
incident_id,
|
||||
run_id,
|
||||
parent_op_id,
|
||||
actor,
|
||||
dry_run_result,
|
||||
error,
|
||||
duration_ms,
|
||||
tags,
|
||||
input ->> 'action' AS input_action,
|
||||
input ->> 'executor' AS input_executor,
|
||||
input ->> 'execution_backend' AS input_execution_backend,
|
||||
input ->> 'catalog_id' AS input_catalog_id,
|
||||
input ->> 'execution_mode' AS input_execution_mode,
|
||||
input ->> 'approval_source' AS input_approval_source,
|
||||
input ->> 'apply_enabled' AS input_apply_enabled,
|
||||
input ->> 'apply_executed' AS input_apply_executed,
|
||||
input ->> 'check_mode_executed' AS input_check_mode_executed,
|
||||
input ->> 'returncode' AS input_returncode,
|
||||
input ->> 'playbook_id' AS input_playbook_id,
|
||||
input ->> 'playbook_path' AS input_playbook_path,
|
||||
input ->> 'ansible_playbook_path' AS input_ansible_playbook_path,
|
||||
input ->> 'check_mode' AS input_check_mode,
|
||||
input ->> 'not_used_reason' AS input_not_used_reason,
|
||||
output ->> 'action' AS output_action,
|
||||
output ->> 'reason' AS output_reason,
|
||||
output ->> 'executor' AS output_executor,
|
||||
output ->> 'execution_backend' AS output_execution_backend,
|
||||
output ->> 'catalog_id' AS output_catalog_id,
|
||||
output ->> 'execution_mode' AS output_execution_mode,
|
||||
output ->> 'approval_source' AS output_approval_source,
|
||||
output ->> 'apply_enabled' AS output_apply_enabled,
|
||||
output ->> 'apply_executed' AS output_apply_executed,
|
||||
output ->> 'check_mode_executed' AS output_check_mode_executed,
|
||||
output ->> 'returncode' AS output_returncode,
|
||||
output ->> 'playbook_id' AS output_playbook_id,
|
||||
output ->> 'playbook_path' AS output_playbook_path,
|
||||
output ->> 'ansible_playbook_path' AS output_ansible_playbook_path,
|
||||
output ->> 'check_mode' AS output_check_mode,
|
||||
output ->> 'not_used_reason' AS output_not_used_reason,
|
||||
dry_run_result ->> 'returncode' AS dry_run_returncode,
|
||||
dry_run_result ->> 'apply_executed' AS dry_run_apply_executed,
|
||||
dry_run_result ->> 'check_mode_executed'
|
||||
AS dry_run_check_mode_executed,
|
||||
coalesce(input::text, '') AS input_text,
|
||||
coalesce(output::text, '') AS output_text,
|
||||
coalesce(array_to_string(tags, ','), '') AS tags_text,
|
||||
created_at
|
||||
"""
|
||||
bounded_limit = _truth_chain_branch_limit(source_ids, limit)
|
||||
rows_by_id: dict[str, dict[str, Any]] = {}
|
||||
time_predicate = "created_at >= :cutoff" if cutoff is not None else "TRUE"
|
||||
base_params: dict[str, Any] = {
|
||||
"incident_ids": source_ids,
|
||||
"incident_tags": source_ids
|
||||
+ [f"incident_id:{incident_id}" for incident_id in source_ids],
|
||||
}
|
||||
if cutoff is not None:
|
||||
base_params["cutoff"] = cutoff
|
||||
|
||||
async def fetch_branch(
|
||||
where_sql: str, params: dict[str, Any] | None = None
|
||||
) -> None:
|
||||
if len(rows_by_id) >= bounded_limit:
|
||||
return
|
||||
rows = await _fetch_all(
|
||||
db,
|
||||
f"""
|
||||
SELECT
|
||||
{columns}
|
||||
FROM automation_operation_log
|
||||
WHERE {time_predicate}
|
||||
AND ({where_sql})
|
||||
ORDER BY created_at DESC
|
||||
LIMIT :limit
|
||||
""",
|
||||
{
|
||||
**base_params,
|
||||
**(params or {}),
|
||||
"limit": bounded_limit - len(rows_by_id),
|
||||
},
|
||||
)
|
||||
for row in rows:
|
||||
op_id = str(row.get("op_id") or "")
|
||||
if op_id:
|
||||
rows_by_id.setdefault(op_id, row)
|
||||
|
||||
await fetch_branch("incident_id::text = ANY(CAST(:incident_ids AS text[]))")
|
||||
await fetch_branch("input ->> 'incident_id' = ANY(CAST(:incident_ids AS text[]))")
|
||||
await fetch_branch("output ->> 'incident_id' = ANY(CAST(:incident_ids AS text[]))")
|
||||
await fetch_branch(
|
||||
"coalesce(input #> '{source_refs,incident_ids}', '[]'::jsonb) "
|
||||
"?| CAST(:incident_ids AS text[])"
|
||||
)
|
||||
await fetch_branch(
|
||||
"coalesce(output #> '{source_refs,incident_ids}', '[]'::jsonb) "
|
||||
"?| CAST(:incident_ids AS text[])"
|
||||
)
|
||||
await fetch_branch("tags && CAST(:incident_tags AS text[])")
|
||||
|
||||
if allow_text_fallback and len(source_ids) == 1:
|
||||
fallback_params = {"needle": f"%{source_ids[0]}%"}
|
||||
await fetch_branch("coalesce(input::text, '') LIKE :needle", fallback_params)
|
||||
await fetch_branch("coalesce(output::text, '') LIKE :needle", fallback_params)
|
||||
|
||||
return sorted(
|
||||
rows_by_id.values(),
|
||||
key=lambda row: str(row.get("created_at") or ""),
|
||||
reverse=True,
|
||||
)[:bounded_limit]
|
||||
|
||||
|
||||
async def _fetch_outbound_rows_for_incidents(
|
||||
db: Any,
|
||||
*,
|
||||
project_id: str,
|
||||
incident_ids: list[str],
|
||||
limit: int,
|
||||
cutoff: datetime | None = None,
|
||||
allow_text_fallback: bool = False,
|
||||
) -> list[dict[str, Any]]:
|
||||
"""Fetch outbound receipts without casting the full envelope to text."""
|
||||
source_ids = list(dict.fromkeys(str(value) for value in incident_ids if value))
|
||||
if not source_ids:
|
||||
return []
|
||||
|
||||
columns = """
|
||||
message_id,
|
||||
project_id,
|
||||
run_id,
|
||||
channel_type,
|
||||
message_type,
|
||||
content_hash,
|
||||
content_preview,
|
||||
content_redacted,
|
||||
redaction_version,
|
||||
source_envelope,
|
||||
provider_message_id,
|
||||
send_status,
|
||||
queued_at,
|
||||
sent_at,
|
||||
triggered_by_state
|
||||
"""
|
||||
bounded_limit = _truth_chain_branch_limit(source_ids, limit)
|
||||
rows_by_id: dict[str, dict[str, Any]] = {}
|
||||
time_predicate = "queued_at >= :cutoff" if cutoff is not None else "TRUE"
|
||||
valid_run_ids: list[str] = []
|
||||
for source_id in source_ids:
|
||||
try:
|
||||
valid_run_ids.append(str(UUID(source_id)))
|
||||
except ValueError:
|
||||
continue
|
||||
base_params: dict[str, Any] = {
|
||||
"project_id": project_id,
|
||||
"incident_ids": source_ids,
|
||||
}
|
||||
if cutoff is not None:
|
||||
base_params["cutoff"] = cutoff
|
||||
|
||||
async def fetch_branch(
|
||||
where_sql: str, params: dict[str, Any] | None = None
|
||||
) -> None:
|
||||
if len(rows_by_id) >= bounded_limit:
|
||||
return
|
||||
rows = await _fetch_all(
|
||||
db,
|
||||
f"""
|
||||
SELECT
|
||||
{columns}
|
||||
FROM awooop_outbound_message
|
||||
WHERE project_id = :project_id
|
||||
AND {time_predicate}
|
||||
AND ({where_sql})
|
||||
ORDER BY queued_at DESC
|
||||
LIMIT :limit
|
||||
""",
|
||||
{
|
||||
**base_params,
|
||||
**(params or {}),
|
||||
"limit": bounded_limit - len(rows_by_id),
|
||||
},
|
||||
)
|
||||
for row in rows:
|
||||
message_id = str(row.get("message_id") or "")
|
||||
if message_id:
|
||||
rows_by_id.setdefault(message_id, row)
|
||||
|
||||
if valid_run_ids:
|
||||
await fetch_branch(
|
||||
"run_id = ANY(CAST(:run_ids AS uuid[]))",
|
||||
{"run_ids": valid_run_ids},
|
||||
)
|
||||
for source_ref_path in (
|
||||
"{source_refs,incident_ids}",
|
||||
"{source_refs,code_refs}",
|
||||
):
|
||||
await fetch_branch(
|
||||
f"coalesce(source_envelope #> '{source_ref_path}', '[]'::jsonb) "
|
||||
"?| CAST(:incident_ids AS text[])"
|
||||
)
|
||||
for direct_path in (
|
||||
"{callback_reply,incident_id}",
|
||||
"{alert_notification,incident_id}",
|
||||
"{source_refs,incident_id}",
|
||||
):
|
||||
await fetch_branch(
|
||||
f"source_envelope #>> '{direct_path}' "
|
||||
"= ANY(CAST(:incident_ids AS text[]))"
|
||||
)
|
||||
await fetch_branch(
|
||||
"source_envelope ->> 'incident_id' "
|
||||
"= ANY(CAST(:incident_ids AS text[]))"
|
||||
)
|
||||
|
||||
if allow_text_fallback and len(source_ids) == 1:
|
||||
await fetch_branch(
|
||||
"content_preview ILIKE :needle",
|
||||
{"needle": f"%{source_ids[0]}%"},
|
||||
)
|
||||
|
||||
return sorted(
|
||||
rows_by_id.values(),
|
||||
key=lambda row: str(row.get("queued_at") or ""),
|
||||
reverse=True,
|
||||
)[:bounded_limit]
|
||||
|
||||
|
||||
def _source_type(source_id: str, incident: dict[str, Any] | None, drift: dict[str, Any] | None) -> str:
|
||||
if incident is not None:
|
||||
return "incident"
|
||||
@@ -1698,65 +1973,11 @@ async def fetch_truth_chain(source_id: str, project_id: str = "awoooi") -> dict[
|
||||
""",
|
||||
{"incident_id": incident_id, "limit": _MAX_ROWS},
|
||||
)
|
||||
automation_ops = await _fetch_all(
|
||||
automation_ops = await _fetch_automation_operation_rows_for_incidents(
|
||||
db,
|
||||
"""
|
||||
SELECT
|
||||
op_id,
|
||||
operation_type,
|
||||
status,
|
||||
incident_id,
|
||||
run_id,
|
||||
parent_op_id,
|
||||
actor,
|
||||
dry_run_result,
|
||||
error,
|
||||
duration_ms,
|
||||
tags,
|
||||
input ->> 'action' AS input_action,
|
||||
input ->> 'executor' AS input_executor,
|
||||
input ->> 'execution_backend' AS input_execution_backend,
|
||||
input ->> 'catalog_id' AS input_catalog_id,
|
||||
input ->> 'execution_mode' AS input_execution_mode,
|
||||
input ->> 'approval_source' AS input_approval_source,
|
||||
input ->> 'apply_enabled' AS input_apply_enabled,
|
||||
input ->> 'apply_executed' AS input_apply_executed,
|
||||
input ->> 'check_mode_executed' AS input_check_mode_executed,
|
||||
input ->> 'returncode' AS input_returncode,
|
||||
input ->> 'playbook_id' AS input_playbook_id,
|
||||
input ->> 'playbook_path' AS input_playbook_path,
|
||||
input ->> 'ansible_playbook_path' AS input_ansible_playbook_path,
|
||||
input ->> 'check_mode' AS input_check_mode,
|
||||
input ->> 'not_used_reason' AS input_not_used_reason,
|
||||
output ->> 'action' AS output_action,
|
||||
output ->> 'reason' AS output_reason,
|
||||
output ->> 'executor' AS output_executor,
|
||||
output ->> 'execution_backend' AS output_execution_backend,
|
||||
output ->> 'catalog_id' AS output_catalog_id,
|
||||
output ->> 'execution_mode' AS output_execution_mode,
|
||||
output ->> 'approval_source' AS output_approval_source,
|
||||
output ->> 'apply_enabled' AS output_apply_enabled,
|
||||
output ->> 'apply_executed' AS output_apply_executed,
|
||||
output ->> 'check_mode_executed' AS output_check_mode_executed,
|
||||
output ->> 'returncode' AS output_returncode,
|
||||
output ->> 'playbook_id' AS output_playbook_id,
|
||||
output ->> 'playbook_path' AS output_playbook_path,
|
||||
output ->> 'ansible_playbook_path' AS output_ansible_playbook_path,
|
||||
output ->> 'check_mode' AS output_check_mode,
|
||||
output ->> 'not_used_reason' AS output_not_used_reason,
|
||||
dry_run_result ->> 'returncode' AS dry_run_returncode,
|
||||
dry_run_result ->> 'apply_executed' AS dry_run_apply_executed,
|
||||
dry_run_result ->> 'check_mode_executed' AS dry_run_check_mode_executed,
|
||||
created_at
|
||||
FROM automation_operation_log
|
||||
WHERE incident_id::text = :incident_id
|
||||
OR coalesce(input::text, '') LIKE :needle
|
||||
OR coalesce(output::text, '') LIKE :needle
|
||||
OR coalesce(array_to_string(tags, ','), '') LIKE :needle
|
||||
ORDER BY created_at DESC
|
||||
LIMIT :limit
|
||||
""",
|
||||
{"incident_id": incident_id, "needle": f"%{incident_id}%", "limit": _MAX_ROWS},
|
||||
incident_ids=[incident_id],
|
||||
limit=_MAX_ROWS,
|
||||
allow_text_fallback=True,
|
||||
)
|
||||
auto_repair_executions = await _fetch_all(
|
||||
db,
|
||||
@@ -1871,42 +2092,12 @@ async def fetch_truth_chain(source_id: str, project_id: str = "awoooi") -> dict[
|
||||
fingerprint_value=fingerprint_value,
|
||||
limit=_MAX_ROWS,
|
||||
)
|
||||
outbound_rows = await _fetch_all(
|
||||
outbound_rows = await _fetch_outbound_rows_for_incidents(
|
||||
db,
|
||||
"""
|
||||
SELECT
|
||||
message_id,
|
||||
project_id,
|
||||
run_id,
|
||||
channel_type,
|
||||
message_type,
|
||||
content_hash,
|
||||
content_preview,
|
||||
content_redacted,
|
||||
redaction_version,
|
||||
source_envelope,
|
||||
provider_message_id,
|
||||
send_status,
|
||||
queued_at,
|
||||
sent_at,
|
||||
triggered_by_state
|
||||
FROM awooop_outbound_message
|
||||
WHERE project_id = :project_id
|
||||
AND (
|
||||
run_id::text = :source_id
|
||||
OR content_preview ILIKE :needle
|
||||
OR coalesce(source_envelope #> '{source_refs,incident_ids}', '[]'::jsonb) ? :source_id
|
||||
OR coalesce(source_envelope #> '{source_refs,code_refs}', '[]'::jsonb) ? :source_id
|
||||
)
|
||||
ORDER BY queued_at DESC
|
||||
LIMIT :limit
|
||||
""",
|
||||
{
|
||||
"source_id": source_id,
|
||||
"project_id": project_id,
|
||||
"needle": f"%{source_id}%",
|
||||
"limit": _MAX_ROWS,
|
||||
},
|
||||
project_id=project_id,
|
||||
incident_ids=[source_id],
|
||||
limit=_MAX_ROWS,
|
||||
allow_text_fallback=True,
|
||||
)
|
||||
|
||||
source_type = _source_type(source_id, incident, drift)
|
||||
@@ -2244,6 +2435,10 @@ async def fetch_automation_quality_summary(
|
||||
cutoff = datetime.now(UTC) - timedelta(hours=bounded_hours)
|
||||
|
||||
async with get_db_context(normalized_project_id) as db:
|
||||
await db.execute(
|
||||
text("SELECT set_config('statement_timeout', :timeout, true)"),
|
||||
{"timeout": f"{_QUALITY_SUMMARY_STATEMENT_TIMEOUT_MS}ms"},
|
||||
)
|
||||
incidents = await _fetch_all(
|
||||
db,
|
||||
"""
|
||||
@@ -2313,7 +2508,11 @@ async def fetch_automation_quality_summary(
|
||||
if not incident_ids:
|
||||
records = []
|
||||
else:
|
||||
batch_params = {"incident_ids": incident_ids, "limit": _MAX_ROWS * len(incident_ids)}
|
||||
batch_row_limit = min(
|
||||
_MAX_ROWS * len(incident_ids),
|
||||
_QUALITY_SUMMARY_MAX_BATCH_ROWS,
|
||||
)
|
||||
batch_params = {"incident_ids": incident_ids, "limit": batch_row_limit}
|
||||
approvals = await _fetch_all(
|
||||
db,
|
||||
"""
|
||||
@@ -2415,72 +2614,11 @@ async def fetch_automation_quality_summary(
|
||||
""",
|
||||
batch_params,
|
||||
)
|
||||
automation_ops = await _fetch_all(
|
||||
automation_ops = await _fetch_automation_operation_rows_for_incidents(
|
||||
db,
|
||||
"""
|
||||
SELECT
|
||||
op_id,
|
||||
operation_type,
|
||||
status,
|
||||
incident_id,
|
||||
run_id,
|
||||
parent_op_id,
|
||||
actor,
|
||||
dry_run_result,
|
||||
error,
|
||||
duration_ms,
|
||||
tags,
|
||||
input ->> 'action' AS input_action,
|
||||
input ->> 'executor' AS input_executor,
|
||||
input ->> 'execution_backend' AS input_execution_backend,
|
||||
input ->> 'catalog_id' AS input_catalog_id,
|
||||
input ->> 'execution_mode' AS input_execution_mode,
|
||||
input ->> 'approval_source' AS input_approval_source,
|
||||
input ->> 'apply_enabled' AS input_apply_enabled,
|
||||
input ->> 'apply_executed' AS input_apply_executed,
|
||||
input ->> 'check_mode_executed' AS input_check_mode_executed,
|
||||
input ->> 'returncode' AS input_returncode,
|
||||
input ->> 'playbook_id' AS input_playbook_id,
|
||||
input ->> 'playbook_path' AS input_playbook_path,
|
||||
input ->> 'ansible_playbook_path' AS input_ansible_playbook_path,
|
||||
input ->> 'check_mode' AS input_check_mode,
|
||||
input ->> 'not_used_reason' AS input_not_used_reason,
|
||||
output ->> 'action' AS output_action,
|
||||
output ->> 'reason' AS output_reason,
|
||||
output ->> 'executor' AS output_executor,
|
||||
output ->> 'execution_backend' AS output_execution_backend,
|
||||
output ->> 'catalog_id' AS output_catalog_id,
|
||||
output ->> 'execution_mode' AS output_execution_mode,
|
||||
output ->> 'approval_source' AS output_approval_source,
|
||||
output ->> 'apply_enabled' AS output_apply_enabled,
|
||||
output ->> 'apply_executed' AS output_apply_executed,
|
||||
output ->> 'check_mode_executed' AS output_check_mode_executed,
|
||||
output ->> 'returncode' AS output_returncode,
|
||||
output ->> 'playbook_id' AS output_playbook_id,
|
||||
output ->> 'playbook_path' AS output_playbook_path,
|
||||
output ->> 'ansible_playbook_path' AS output_ansible_playbook_path,
|
||||
output ->> 'check_mode' AS output_check_mode,
|
||||
output ->> 'not_used_reason' AS output_not_used_reason,
|
||||
dry_run_result ->> 'returncode' AS dry_run_returncode,
|
||||
dry_run_result ->> 'apply_executed' AS dry_run_apply_executed,
|
||||
dry_run_result ->> 'check_mode_executed' AS dry_run_check_mode_executed,
|
||||
coalesce(input::text, '') AS input_text,
|
||||
coalesce(output::text, '') AS output_text,
|
||||
coalesce(array_to_string(tags, ','), '') AS tags_text,
|
||||
created_at
|
||||
FROM automation_operation_log
|
||||
WHERE incident_id::text = ANY(CAST(:incident_ids AS text[]))
|
||||
OR EXISTS (
|
||||
SELECT 1
|
||||
FROM unnest(CAST(:incident_ids AS text[])) AS source_ids(incident_id)
|
||||
WHERE coalesce(input::text, '') LIKE '%' || source_ids.incident_id || '%'
|
||||
OR coalesce(output::text, '') LIKE '%' || source_ids.incident_id || '%'
|
||||
OR coalesce(array_to_string(tags, ','), '') LIKE '%' || source_ids.incident_id || '%'
|
||||
)
|
||||
ORDER BY created_at DESC
|
||||
LIMIT :limit
|
||||
""",
|
||||
batch_params,
|
||||
incident_ids=incident_ids,
|
||||
limit=batch_row_limit,
|
||||
cutoff=cutoff,
|
||||
)
|
||||
auto_repair_executions = await _fetch_all(
|
||||
db,
|
||||
@@ -2550,40 +2688,12 @@ async def fetch_automation_quality_summary(
|
||||
""",
|
||||
{**batch_params, "project_id": normalized_project_id},
|
||||
)
|
||||
outbound_rows = await _fetch_all(
|
||||
outbound_rows = await _fetch_outbound_rows_for_incidents(
|
||||
db,
|
||||
"""
|
||||
SELECT
|
||||
message_id,
|
||||
project_id,
|
||||
run_id,
|
||||
channel_type,
|
||||
message_type,
|
||||
content_hash,
|
||||
content_preview,
|
||||
content_redacted,
|
||||
redaction_version,
|
||||
source_envelope,
|
||||
provider_message_id,
|
||||
send_status,
|
||||
queued_at,
|
||||
sent_at,
|
||||
triggered_by_state
|
||||
FROM awooop_outbound_message
|
||||
WHERE project_id = :project_id
|
||||
AND (
|
||||
run_id::text = ANY(CAST(:incident_ids AS text[]))
|
||||
OR EXISTS (
|
||||
SELECT 1
|
||||
FROM unnest(CAST(:incident_ids AS text[])) AS source_ids(incident_id)
|
||||
WHERE coalesce(content_preview, '') ILIKE '%' || source_ids.incident_id || '%'
|
||||
OR coalesce(source_envelope::text, '') LIKE '%' || source_ids.incident_id || '%'
|
||||
)
|
||||
)
|
||||
ORDER BY queued_at DESC
|
||||
LIMIT :limit
|
||||
""",
|
||||
{**batch_params, "project_id": normalized_project_id},
|
||||
project_id=normalized_project_id,
|
||||
incident_ids=incident_ids,
|
||||
limit=batch_row_limit,
|
||||
cutoff=cutoff,
|
||||
)
|
||||
|
||||
approvals_by_incident = _group_rows_by_incident_reference(
|
||||
|
||||
Reference in New Issue
Block a user