From b64b11c9acda71a5070113f9c83c810dcf12c95d Mon Sep 17 00:00:00 2001 From: Vidya Nambiar Date: Fri, 25 Sep 2026 10:50:37 -0400 Subject: [PATCH] [AAP-86051] Document serializer persistence context for bulk bypass dedupe Point bulk host/job launch create() and workflow bulk audit at DAB validation_bypass_observability guidance for is_valid() + audit_bulk_*. Co-authored-by: Cursor --- awx/api/serializers.py | 2 ++ awx/main/utils/validation_bypass_observability.py | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index f4aab86136..22ca4b6490 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -2274,6 +2274,7 @@ class BulkHostCreateSerializer(serializers.Serializer): return attrs def create(self, validated_data): + # DAB: dedupe Validation rejected (child BulkHostSerializer is_valid) vs ORM bypass bulk_create. with serializer_mediated_persistence_context(): return self._create_bulk_hosts(validated_data) @@ -5282,6 +5283,7 @@ class BulkJobLaunchSerializer(PromptFieldCleanTextMixin, serializers.Serializer) ) def create(self, validated_data): + # DAB: dedupe Validation rejected (is_valid) vs audit_workflow_job_nodes / bulk_create bypass logs. with serializer_mediated_persistence_context(): return self._create_bulk_job_launch(validated_data) diff --git a/awx/main/utils/validation_bypass_observability.py b/awx/main/utils/validation_bypass_observability.py index 7725eb3277..7c4c83a1f2 100644 --- a/awx/main/utils/validation_bypass_observability.py +++ b/awx/main/utils/validation_bypass_observability.py @@ -61,6 +61,11 @@ def audit_workflow_job_nodes_for_bulk_create(nodes: Iterable[Model]) -> None: columns. Node prompt values (limit, job_tags, etc.) live in ``char_prompts`` via ``NullablePromptPseudoField`` and must be read with ``getattr`` after deferred attrs are applied on the in-memory instances. + + When called from a DRF ``create()`` after ``is_valid()``, the caller must run + inside DAB ``serializer_mediated_persistence_context`` so duplicate + ``Validation rejected`` / ``ORM bypass`` lines are not emitted (see DAB + ``docs/lib/validation_bypass_observability.md``). """ materialized = list(nodes) if not materialized: