mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
Dispatch the abandon flow last for a fired deal-change 🟩
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ecdcf12050
commit
8aa2841546
1 changed files with 30 additions and 5 deletions
|
|
@ -1,11 +1,13 @@
|
|||
"""Dispatches the flows named in a trigger message through the orchestrator.
|
||||
|
||||
The scraper decides which flows fire; this is a dumb dispatcher. Flows run
|
||||
in a fixed, retry-safe order — amend, then log, then tenant sync — so that
|
||||
redelivery re-runs idempotent flows before non-idempotent ones: amend is
|
||||
naturally idempotent, log is guarded by the job-number check, and tenant
|
||||
contact creation (not idempotent) runs last so its failure can never cause
|
||||
a duplicate job log, and a log failure can never duplicate contacts.
|
||||
in a fixed, retry-safe order — amend, then log, then tenant sync, then
|
||||
abandon — so that redelivery re-runs idempotent flows before non-idempotent
|
||||
ones: amend is naturally idempotent, log is guarded by the job-number check,
|
||||
and tenant contact creation (not idempotent) runs before abandon so its
|
||||
failure can never cause a duplicate job log, and a log failure can never
|
||||
duplicate contacts. Abandon runs last so a cancellation can never interfere
|
||||
with a log, amend or tenant sync in the same batch.
|
||||
"""
|
||||
|
||||
from typing import Dict, Protocol
|
||||
|
|
@ -13,9 +15,11 @@ from typing import Dict, Protocol
|
|||
from applications.abri.abri_trigger_request import AbriTriggerRequest
|
||||
from domain.abri.models import AbriRequestRejected, PlaceRef
|
||||
from orchestration.abri_orchestrator import (
|
||||
AbandonJobOrchestrationResult,
|
||||
AmendJobOrchestrationResult,
|
||||
AppointmentChange,
|
||||
ConfirmedSurveyBooking,
|
||||
DealAbandonment,
|
||||
DealDatabaseGateway,
|
||||
LogJobOrchestrationResult,
|
||||
LogJobWriteBackError,
|
||||
|
|
@ -35,6 +39,10 @@ class AbriFlows(Protocol):
|
|||
self, place_ref: PlaceRef, deal_id: str
|
||||
) -> TenantDataSyncResult: ...
|
||||
|
||||
def abandon_job(
|
||||
self, abandonment: DealAbandonment
|
||||
) -> AbandonJobOrchestrationResult: ...
|
||||
|
||||
|
||||
class AbriFlowRejectedError(Exception):
|
||||
"""An OpenHousing rejection, surfaced as a failure so the task fails.
|
||||
|
|
@ -66,6 +74,8 @@ def dispatch_abri_flows(
|
|||
summary["log_job"] = _run_log(request, flows, deal_database)
|
||||
if "sync_tenant_data" in request.flows:
|
||||
summary["sync_tenant_data"] = _run_tenant_sync(request, flows)
|
||||
if "abandon_job" in request.flows:
|
||||
summary["abandon_job"] = _run_abandon(request, flows)
|
||||
|
||||
return summary
|
||||
|
||||
|
|
@ -122,6 +132,21 @@ def _run_log(
|
|||
return f"job {outcome.job_no} logged"
|
||||
|
||||
|
||||
def _run_abandon(request: AbriTriggerRequest, flows: AbriFlows) -> str:
|
||||
# Runs last so a cancellation can never interfere with a log, amend or
|
||||
# tenant sync in the same batch. A missing job_no raises the retriable
|
||||
# not-yet-recorded error, which propagates so the task fails and redelivers.
|
||||
outcome = flows.abandon_job(
|
||||
DealAbandonment(
|
||||
deal_id=request.hubspot_deal_id,
|
||||
outcome=request.outcome,
|
||||
)
|
||||
)
|
||||
if isinstance(outcome, AbriRequestRejected):
|
||||
raise AbriFlowRejectedError(flow="abandon_job", rejection=outcome)
|
||||
return f"job {outcome.job_no} abandoned"
|
||||
|
||||
|
||||
def _run_tenant_sync(request: AbriTriggerRequest, flows: AbriFlows) -> str:
|
||||
if request.place_ref is None:
|
||||
raise ValueError("sync_tenant_data fired without a place_ref")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue