feat(campaign): persist delivery execution mode

This commit is contained in:
2026-07-22 08:37:58 +02:00
parent aa4ec66b7b
commit 62a68792a4
9 changed files with 373 additions and 4 deletions

View File

@@ -87,6 +87,10 @@ def _version_info(
),
"execution_snapshot_hash": version.execution_snapshot_hash,
"execution_snapshot_at": version.execution_snapshot_at.isoformat() if version.execution_snapshot_at else None,
"delivery_mode": version.delivery_mode,
"delivery_mode_selected_at": (
version.delivery_mode_selected_at.isoformat() if version.delivery_mode_selected_at else None
),
}
@@ -110,6 +114,12 @@ def _load_delivery_info(
"queueable_job_count": 0,
"estimated_remaining_send_seconds": None,
"estimated_remaining_send_human": None,
"delivery_mode": version.delivery_mode if version else None,
"delivery_mode_selected_at": (
version.delivery_mode_selected_at.isoformat()
if version and version.delivery_mode_selected_at
else None
),
}
if include_diagnostics:
default.update(
@@ -159,6 +169,10 @@ def _load_delivery_info(
"queueable_job_count": snapshot.queueable_job_count,
"estimated_remaining_send_seconds": estimated_seconds,
"estimated_remaining_send_human": _human_duration(estimated_seconds),
"delivery_mode": version.delivery_mode,
"delivery_mode_selected_at": (
version.delivery_mode_selected_at.isoformat() if version.delivery_mode_selected_at else None
),
}
if include_diagnostics:
result.update(
@@ -544,6 +558,27 @@ def _campaign_report_cards(version: CampaignVersion | None, jobs: list[CampaignJ
send_counts = _counter([job.send_status for job in jobs])
imap_counts = _counter([job.imap_status for job in jobs])
queueable = sum(1 for job in jobs if job.validation_status in {"ready", "warning"} and job.build_status == "built")
queueable_unattempted = sum(
1
for job in jobs
if job.attempt_count == 0
and job.send_status in {"not_queued", "cancelled"}
and job.validation_status in {"ready", "warning"}
and job.build_status == "built"
)
retry_max_attempts = _retry_max_attempts(version)
retryable = sum(
1
for job in jobs
if job.send_status == "failed_temporary"
and (retry_max_attempts is None or job.attempt_count < retry_max_attempts)
)
cancellable = sum(
1
for job in jobs
if job.send_status
not in {"smtp_accepted", "sent", "outcome_unknown", "claimed", "sending", "cancelled"}
)
needs_attention = sum(
1
for job in jobs
@@ -562,6 +597,9 @@ def _campaign_report_cards(version: CampaignVersion | None, jobs: list[CampaignJ
"jobs_total": len(jobs),
"inactive": inactive_entries,
"queueable": queueable,
"queueable_unattempted": queueable_unattempted,
"retryable": retryable,
"cancellable": cancellable,
"needs_attention": needs_attention,
"sent": sent,
"smtp_accepted": sent,
@@ -576,6 +614,15 @@ def _campaign_report_cards(version: CampaignVersion | None, jobs: list[CampaignJ
}
def _retry_max_attempts(version: CampaignVersion | None) -> int | None:
if version is None or not isinstance(version.execution_snapshot, dict):
return None
try:
return ExecutionSnapshot.model_validate(version.execution_snapshot).delivery.retry.max_attempts
except Exception:
return None
def _inactive_entry_count(version: CampaignVersion | None) -> int:
build_summary = version.build_summary if version and isinstance(version.build_summary, dict) else {}
return int(build_summary.get("inactive_count") or build_summary.get("inactive_entries_count") or 0)