Bind Mail effects to stable delivery attempts
This commit is contained in:
@@ -76,6 +76,13 @@ and uncertain or stranded effects remain `outcome_unknown` or
|
||||
`recovery_required` in Ops. Campaign jobs, message actions, and channel-attempt
|
||||
records remain the business source of truth.
|
||||
|
||||
For SMTP and Sent-folder APPEND, Campaign also passes the stable job/action and
|
||||
attempt identifier into Mail. Mail establishes its own provider-bound recovery
|
||||
fence after profile authorization and policy checks but before network I/O.
|
||||
This nested ownership is intentional: Campaign proves its business transition,
|
||||
while Mail proves the transport effect. Neither layer replays a completed or
|
||||
unknown provider attempt merely to repair the other layer's state.
|
||||
|
||||
- `smtp_accepted`: Do not retry. If IMAP append is enabled and pending, run or
|
||||
enqueue the append action.
|
||||
- `failed_temporary`: Retry explicitly after checking the error and retry count.
|
||||
|
||||
@@ -2321,6 +2321,11 @@ def _perform_single_message_direct_effect(
|
||||
),
|
||||
smtp_server_id=delivery_context.snapshot.smtp_server_id,
|
||||
smtp_credential_id=delivery_context.snapshot.smtp_credential_id,
|
||||
recovery_effect_id=(
|
||||
f"campaign-single:{action.id}:smtp-attempt:{attempt.attempt_number}"
|
||||
),
|
||||
recovery_resource_type="campaign_message_action",
|
||||
recovery_resource_id=action.id,
|
||||
)
|
||||
except SmtpSendError as exc:
|
||||
if exc.outcome_unknown:
|
||||
@@ -3633,6 +3638,11 @@ def _send_claimed_mail_only_job(
|
||||
or "",
|
||||
smtp_server_id=context.snapshot.smtp_server_id,
|
||||
smtp_credential_id=context.snapshot.smtp_credential_id,
|
||||
recovery_effect_id=(
|
||||
f"campaign-job:{job.id}:smtp-attempt:{attempt.attempt_number}"
|
||||
),
|
||||
recovery_resource_type="campaign_job",
|
||||
recovery_resource_id=job.id,
|
||||
)
|
||||
if result.accepted_count <= 0:
|
||||
raise SmtpSendError(
|
||||
@@ -4780,6 +4790,11 @@ def _invoke_imap_append(
|
||||
smtp_credential_id=snapshot.smtp_credential_id,
|
||||
imap_server_id=snapshot.imap_server_id,
|
||||
imap_credential_id=snapshot.imap_credential_id,
|
||||
recovery_effect_id=(
|
||||
f"campaign-job:{job.id}:imap-attempt:{claimed.attempt.attempt_number}"
|
||||
),
|
||||
recovery_resource_type="campaign_job",
|
||||
recovery_resource_id=job.id,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -181,7 +181,10 @@ class CampaignQueueSelectionTests(unittest.TestCase):
|
||||
)
|
||||
with (
|
||||
patch("govoplan_campaign.backend.sending.jobs.mail_integration", return_value=Mail()),
|
||||
patch("govoplan_campaign.backend.sending.jobs._record_attempt_start", return_value=object()),
|
||||
patch(
|
||||
"govoplan_campaign.backend.sending.jobs._record_attempt_start",
|
||||
return_value=SimpleNamespace(attempt_number=1),
|
||||
),
|
||||
patch(
|
||||
"govoplan_campaign.backend.sending.jobs._record_smtp_send_success",
|
||||
side_effect=OSError("storage unavailable"),
|
||||
|
||||
Reference in New Issue
Block a user