diff --git a/api/app/Services/FormBuilder/FormFailureRetryService.php b/api/app/Services/FormBuilder/FormFailureRetryService.php index 7361bf83..55a4c91a 100644 --- a/api/app/Services/FormBuilder/FormFailureRetryService.php +++ b/api/app/Services/FormBuilder/FormFailureRetryService.php @@ -8,6 +8,7 @@ use App\Enums\FormBuilder\ApplyStatus; use App\Exceptions\FormBuilder\FailureNotRetriableException; use App\Exceptions\FormBuilder\ParentSubmissionGoneException; use App\FormBuilder\Bindings\FormBindingApplicator; +use App\FormBuilder\Bindings\FormBindingExceptionClassifier; use App\Models\FormBuilder\FormSubmission; use App\Models\FormBuilder\FormSubmissionActionFailure; use App\Models\FormBuilder\FormSubmissionActionFailureRetryAttempt; @@ -30,6 +31,13 @@ use Throwable; * exception details, increment retry_count. Parent's own * exception_class / exception_message stay audit-immutable — * they represent the FIRST failure. + * + * v1.3-delta D2 (per ARCH-BINDINGS §7.1 v1.2 + RFC-WS-6 §Q3 v1.3 addition 2): + * - recordFailure now mirrors ApplyBindingsOnFormSubmit's outer-txn path: + * writes failure_response_code via FormBindingExceptionClassifier and + * apply_completed_at = now() (closes the asymmetry where the listener + * wrote this column on both happy and failure paths but the retry + * service only wrote it on the success path). */ final readonly class FormFailureRetryService { @@ -125,9 +133,18 @@ final readonly class FormFailureRetryService ->whereKey($failure->id) ->update(['retry_count' => DB::raw('retry_count + 1')]); + // Per ARCH-BINDINGS §7.1 v1.2 retry-service asymmetry note + + // RFC-WS-6 §Q3 v1.3 addition 2 — mirror ApplyBindingsOnFormSubmit's + // outer-transaction failure path: same failure_response_code + // classifier + apply_completed_at write. Single behaviour-change + // point per the v1.3-delta D1 design. FormSubmission::query() ->whereKey($submission->id) - ->update(['apply_status' => ApplyStatus::FAILED->value]); + ->update([ + 'apply_status' => ApplyStatus::FAILED->value, + 'apply_completed_at' => now(), + 'failure_response_code' => FormBindingExceptionClassifier::classify($e), + ]); return $attempt; });