Skip to content

GOV-667 | feat: Prevent duplicate AuthPolicy creation on timeout retries#878

Merged
Aryamanz29 merged 5 commits intomainfrom
GOV-667
Mar 25, 2026
Merged

GOV-667 | feat: Prevent duplicate AuthPolicy creation on timeout retries#878
Aryamanz29 merged 5 commits intomainfrom
GOV-667

Conversation

@ankitpatnaik-atlan
Copy link
Copy Markdown
Contributor

@ankitpatnaik-atlan ankitpatnaik-atlan commented Mar 24, 2026

Overview

Prevents duplicate metadata policy creation when API requests timeout and are retried. The solution adds intelligent duplicate detection only during API attempts, preserving existing functionality while preventing duplicates caused by timeout-retry scenarios.

Problem

When creating metadata policies in tenants with 700+ existing policies:

  1. API request takes 47+ seconds to complete
  2. Client times out (default 30s) and triggers retry
  3. Original request actually succeeds on the server
  4. Retry creates a duplicate policy with the same name
  5. Multiple retries → multiple duplicate policies

Solution

Smart Request Handling with Duplicate Detection

The fix modifies the transport retry logic to check for existing policies before every API attempt (first attempt +
retries):

NORMAL FLOW (no existing policy):
✅ Check for duplicate → Not found
✅ Create policy → Success

TIMEOUT + RETRY FLOW:
⏱️ Check for duplicate → Not found
⏱️ Create policy → Timeout (but succeeds server-side)
🔍 Before retry: Check for duplicate → Found!
✅ Return existing policy (prevent duplicate)

AUTOMATION RE-RUN:
🔍 Check for duplicate → Found!
✅ Return existing policy (idempotent)

Changes Made

1. New Module: pyatlan/client/common/transport.py

Shared utilities for duplicate AuthPolicy detection:

  • parse_auth_policy_entity() - Extracts policy metadata from bulk POST requests
  • build_policy_search_request() - Constructs IndexSearch query for existing policies
  • get_persona_qualified_name() / get_persona_qualified_name_async() - Resolves persona QN by GUID
  • find_existing_policy() / find_existing_policy_async() - Searches for existing policy by name + persona
  • check_for_duplicate_policy() / check_for_duplicate_policy_async() - Main duplicate check orchestration
  • create_mock_response() - Creates HTTP response with existing policy data

2. Enhanced Transport: pyatlan/client/transport.py

Modified both sync and async transports:

  • Added client parameter to store AtlanClient reference
  • Enhanced _retry_operation() / _retry_operation_async() to check for duplicates before every attempt
  • If duplicate found: returns mock response immediately (no API call)
  • If search fails: degrades gracefully and proceeds with request (never blocks legitimate operations)

3. New Error Codes: pyatlan/errors.py

Added error codes for duplicate prevention:

  • UNABLE_TO_SEARCH_EXISTING_POLICY (ATLAN-PYTHON-500-007)
  • UNABLE_TO_RESOLVE_PERSONA_QUALIFIED_NAME (ATLAN-PYTHON-500-008)

4. Comprehensive Test Coverage

Unit tests (tests/unit/test_transport.py):

  • Parse AuthPolicy entity from bulk requests
  • Build search requests
  • Find existing policies (sync + async)
  • Check for duplicates (sync + async)
  • Transport retry behavior with duplicate prevention
  • Graceful degradation on search failures

Integration tests (tests/integration/test_transport.py, tests/integration/aio/test_transport.py):

  • Real timeout → retry → duplicate prevention flow
  • Real IndexSearch against live tenant
  • Short-circuit behavior when duplicate exists
  • Both sync and async implementations

Key Features

Non-breaking: No changes to existing API or customer code required
Targeted: Only affects retry/attempt scenarios (the actual problem)
Safe: Falls back to normal request if duplicate check fails
Logged: Clear warning messages when duplicate detected
Idempotent: Allows safe automation re-runs
Transparent: Users get the policy they want (existing or new)

Graceful Degradation

If the duplicate check search fails (index down, network issue, etc.):

  • Exception is caught and logged as warning
  • Returns None (no duplicate found)
  • Request proceeds normally
  • Trade-off: Better to risk a duplicate than block legitimate policy creation

Performance Impact

  • Minimal overhead: One additional search per API attempt (uses indexed search)
  • Only for AuthPolicy creation: Other operations unaffected
  • Fast search: Uses specific filters (policy name + persona QN)
  • Fail-safe: Search failure never blocks the operation

Backwards Compatibility

Fully backwards compatible:

  • No API changes
  • No customer code changes required
  • Existing functionality preserved
  • Only affects internal retry/attempt behavior

Testing

All tests passing:

  • ✅ Unit tests (sync + async)
  • ✅ Integration tests against live tenant (sync + async)
  • ✅ Graceful degradation scenarios
  • ✅ Automation re-run scenarios

Related

  • Fixes duplicate policies from timeout retries
  • Enables idempotent policy creation for automation
  • Improves reliability for tenants with 700+ policies

Note

Medium Risk
Changes core HTTP transport retry behavior to perform pre-flight duplicate detection for AuthPolicy bulk creates, which can alter request flow and add extra IndexSearch calls per attempt. While scoped and fail-open, incorrect matching or search latency could impact policy save behavior in edge cases.

Overview
Prevents duplicate AuthPolicy creation by adding a transport-layer duplicate check for bulk policy creates (temp GUIDs) and short-circuiting requests by returning a mock bulk response when an existing policy is found.

Improves the duplicate search to resolve persona GUID to qualifiedName and then search policies using a qualifiedName prefix plus additional filters (ACTIVE, policyCategory=persona), and updates retry logic to run this check before every attempt (first + retries) while treating search failures as non-blocking.

Adds ErrorCode.UNABLE_TO_RESOLVE_PERSONA_QUALIFIED_NAME and updates unit/integration tests to cover first-attempt detection, retry-time detection, update-vs-create parsing, and graceful degradation on search errors.

Written by Cursor Bugbot for commit 04a951a. This will update automatically on new commits. Configure here.

@ankitpatnaik-atlan ankitpatnaik-atlan changed the title GOV-667: Revamp policy duplication check GOV-667 \ Mar 24, 2026
@ankitpatnaik-atlan ankitpatnaik-atlan changed the title GOV-667 \ GOV-667 | feat: Prevent duplicate AuthPolicy creation on timeout retries Mar 24, 2026
Comment thread pyatlan/client/common/transport.py
Copy link
Copy Markdown
Member

@Aryamanz29 Aryamanz29 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good; one minor doubt below:

Comment thread pyatlan/client/common/transport.py
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment thread pyatlan/client/common/transport.py
Copy link
Copy Markdown
Member

@Aryamanz29 Aryamanz29 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - thanks! @ankitpatnaik-atlan

@Aryamanz29 Aryamanz29 merged commit 4d026b0 into main Mar 25, 2026
80 of 89 checks passed
@Aryamanz29 Aryamanz29 deleted the GOV-667 branch March 25, 2026 06:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants