Skip to content

Conversation

@muhammad-ali-e
Copy link
Contributor

@muhammad-ali-e muhammad-ali-e commented Jan 9, 2026

What

  • Added exception handlers for DuplicateTable and UniqueViolation errors in PsycoPgHandler.execute_query()

Why

  • When multiple workers process files concurrently for the same workflow, they attempt to create the same destination table simultaneously
  • PostgreSQL's CREATE TABLE IF NOT EXISTS is not atomic at the catalog level, causing a race condition
  • Both workers pass the "IF NOT EXISTS" check and collide on PostgreSQL's internal type registration (pg_type_typname_nsp_index)
  • This results in psycopg2.errors.UniqueViolation: duplicate key value violates unique constraint "pg_type_typname_nsp_index"

How

  • Catch PsycopgError.DuplicateTable and PsycopgError.UniqueViolation exceptions
  • For CREATE TABLE IF NOT EXISTS queries only, suppress the error (rollback and return)
  • For other query types, re-raise the exception to preserve existing behavior
  • This makes the operation idempotent as intended by the IF NOT EXISTS clause

Can this PR break any existing features. If yes, please list possible items. If no, please explain why.

  • No, this change only adds exception handling for race conditions
  • Normal table creation behavior is unchanged
  • Only CREATE TABLE IF NOT EXISTS queries are affected, and they are idempotent by design
  • Non-race condition errors are still raised properly

Database Migrations

  • None

Env Config

  • None

Relevant Docs

  • PostgreSQL documentation on CREATE TABLE IF NOT EXISTS behavior

Related Issues or PRs

  • UN-2970

Dependencies Versions

  • None

Notes on Testing

  • Test by running multiple concurrent workflow executions that write to the same destination table
  • The race condition should now be handled gracefully with an INFO log instead of an error

Screenshots

N/A

Checklist

I have read and understood the Contribution Guidelines.

…eation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 9, 2026

Summary by CodeRabbit

  • Bug Fixes
    • Improved database resilience: table-creation operations now tolerate concurrent creation attempts and specific unique-constraint race conditions, preventing unnecessary failures during simultaneous deployments or multi-process startups.
    • Transient, non-impactful database errors are now suppressed and logged as informational events to reduce noisy failures.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Adds a constant and helpers to detect CREATE TABLE IF NOT EXISTS and updates the PostgreSQL query executor to catch DuplicateTable and UniqueViolation, rolling back and suppressing those errors when they match the IF NOT EXISTS / race-condition patterns; other errors are re-raised.

Changes

Cohort / File(s) Summary
PostgreSQL concurrency handler
unstract/connectors/src/unstract/connectors/databases/psycopg_handler.py
Added CREATE_TABLE_IF_NOT_EXISTS constant, _is_create_table_if_not_exists and _is_pg_type_race_condition. Extended execute_query to catch PsycopgError.DuplicateTable and PsycopgError.UniqueViolation: rollback, detect IF NOT EXISTS / constraint race conditions, log and suppress when appropriate; otherwise log and re-raise.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Handler
    participant Postgres
    Client->>Handler: execute_query("CREATE TABLE IF NOT EXISTS ...")
    Handler->>Postgres: send SQL
    alt Postgres creates table successfully
        Postgres-->>Handler: success
        Handler-->>Client: success
    else Postgres raises DuplicateTable or UniqueViolation
        Postgres-->>Handler: error (DuplicateTable/UniqueViolation)
        Handler->>Handler: rollback transaction
        alt SQL matches IF NOT EXISTS or constraint race detected
            Handler-->>Client: log info + return (suppress error)
        else
            Handler-->>Client: log error + re-raise
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically describes the main change: handling PostgreSQL race conditions in concurrent table creation, clearly summarizing the fix being implemented.
Description check ✅ Passed The description is comprehensive and follows the template with all major sections completed, including clear explanations of What, Why, How, and testing guidance.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between d830ef6 and b873329.

📒 Files selected for processing (1)
  • unstract/connectors/src/unstract/connectors/databases/psycopg_handler.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (5)
unstract/connectors/src/unstract/connectors/databases/psycopg_handler.py (5)

18-19: LGTM!

Good practice to extract the magic string into a constant for reuse and maintainability.


21-23: LGTM!

Clean helper with appropriate normalization for case-insensitive matching.


26-39: LGTM!

Well-documented helper with clear purpose. The constraint check correctly targets the pg_type_typname_nsp_index unique violation that occurs during concurrent table creation race conditions.


59-68: LGTM!

Correctly handles the DuplicateTable race condition:

  • Rollback ensures transaction is reset from failed state.
  • Suppression is appropriately scoped to only CREATE TABLE IF NOT EXISTS statements.
  • Other DuplicateTable errors are logged with full traceback and re-raised.

69-81: LGTM!

Correctly handles the UniqueViolation race condition on pg_type_typname_nsp_index:

  • Safe nested attribute access pattern for extracting constraint name.
  • Constraint name included in logs aids debugging.
  • Suppression is narrowly scoped to the specific pg_type catalog race condition.
  • Other UniqueViolation errors (actual data constraint violations) are correctly re-raised.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
unstract/connectors/src/unstract/connectors/databases/psycopg_handler.py (2)

38-52: Solid handling of the PostgreSQL race condition.

The approach is correct: catching DuplicateTable, rolling back the aborted transaction, and returning early makes the operation idempotent.

Optional improvement: Consider using startswith instead of in to avoid false positives if the string appears elsewhere in the query (e.g., as a literal in an INSERT).

🔧 Suggested improvement
-        if CREATE_TABLE_IF_NOT_EXISTS in sql_query.upper():
+        if sql_query.strip().upper().startswith(CREATE_TABLE_IF_NOT_EXISTS):

53-66: Race condition handling is appropriate.

This correctly addresses the pg_type_typname_nsp_index UniqueViolation that can occur during concurrent table creation.

Regarding the static analysis hint at line 65: While logging.exception would include the traceback, the existing handlers in this file (lines 68, 71, 74, 77, etc.) all use logger.error. Since the exception is re-raised immediately, the traceback is preserved. Keeping logger.error maintains consistency with the rest of the file.

Same startswith suggestion applies here for line 57.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between fa9c162 and 08ef6c8.

📒 Files selected for processing (1)
  • unstract/connectors/src/unstract/connectors/databases/psycopg_handler.py
🧰 Additional context used
🪛 Ruff (0.14.10)
unstract/connectors/src/unstract/connectors/databases/psycopg_handler.py

51-51: Use logging.exception instead of logging.error

Replace with exception

(TRY400)


65-65: Use logging.exception instead of logging.error

Replace with exception

(TRY400)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (1)
unstract/connectors/src/unstract/connectors/databases/psycopg_handler.py (1)

18-19: LGTM!

Good use of a module-level constant to avoid string repetition and ensure consistent matching.

muhammad-ali-e and others added 2 commits January 9, 2026 14:32
- Extract _is_create_table_if_not_exists helper function
- Use startswith() instead of in for more precise matching
- Remove unnecessary else blocks to reduce complexity

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @unstract/connectors/src/unstract/connectors/databases/psycopg_handler.py:
- Around line 43-69: The UniqueViolation handling in the block catching
PsycopgError.UniqueViolation is too broad; change it to only suppress when
_is_create_table_if_not_exists(sql_query) is true AND the exception's constraint
name equals "pg_type_typname_nsp_index" (the pg_type race), otherwise call
engine.rollback() and re-raise; also replace logger.error(...) with
logger.exception(...) to preserve traceback when logging the suppressed case and
when logging before re-raising. Ensure any path that re-raises calls
engine.rollback() first to avoid leaving the transaction aborted; use the
existing symbols PsycopgError.UniqueViolation, _is_create_table_if_not_exists,
table_name, sql_query, engine, and logger to locate and update the code.
🧹 Nitpick comments (1)
unstract/connectors/src/unstract/connectors/databases/psycopg_handler.py (1)

18-23: Harden CREATE TABLE IF NOT EXISTS detection (comments/whitespace/modifiers).

strip().upper().startswith(...) is easy to bypass with leading SQL comments, extra whitespace/newlines, or CREATE TEMP/UNLOGGED TABLE IF NOT EXISTS .... If your SQL generator ever emits those variants, the race handling won’t trigger.

Proposed refactor (more tolerant regex)
+import re
 import logging
 from typing import Any

 from psycopg2 import errors as PsycopgError

@@
 CREATE_TABLE_IF_NOT_EXISTS = "CREATE TABLE IF NOT EXISTS"

+_CREATE_TABLE_IF_NOT_EXISTS_RE = re.compile(
+    r"^\s*(?:/\*.*?\*/\s*)*(?:--[^\n]*\n\s*)*"
+    r"CREATE\s+(?:TEMP|TEMPORARY|UNLOGGED\s+)?TABLE\s+IF\s+NOT\s+EXISTS\b",
+    re.IGNORECASE | re.DOTALL,
+)
+
 def _is_create_table_if_not_exists(sql_query: str) -> bool:
     """Check if query is a CREATE TABLE IF NOT EXISTS statement."""
-    return sql_query.strip().upper().startswith(CREATE_TABLE_IF_NOT_EXISTS)
+    return bool(_CREATE_TABLE_IF_NOT_EXISTS_RE.match(sql_query))

Please sanity-check this against the actual emitted CREATE TABLE statements in your workflows.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 08ef6c8 and ed01126.

📒 Files selected for processing (1)
  • unstract/connectors/src/unstract/connectors/databases/psycopg_handler.py
🧰 Additional context used
🪛 Ruff (0.14.10)
unstract/connectors/src/unstract/connectors/databases/psycopg_handler.py

55-55: Use logging.exception instead of logging.error

Replace with exception

(TRY400)


68-68: Use logging.exception instead of logging.error

Replace with exception

(TRY400)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
unstract/connectors/src/unstract/connectors/databases/psycopg_handler.py (3)

43-56: Use logger.exception for better tracebacks when re-raising.

When logging before re-raising an exception, logger.exception automatically includes the traceback, aiding debugging.

Suggested fix
-            logger.error(f"DuplicateTable error: {e.pgerror}")
+            logger.exception(f"DuplicateTable error: {e.pgerror}")

62-65: The constraint is None fallback may be overly permissive.

When constraint_name is unavailable (e.g., due to psycopg2/PostgreSQL version differences), any UniqueViolation during a CREATE TABLE IF NOT EXISTS will be suppressed. While this is likely safe for pure DDL statements, verify this assumption holds for your use cases.

Consider logging the raw exception details when constraint is None to aid future debugging:

Optional: Add trace logging when constraint is unknown
             is_pg_type_race = (
                 constraint == "pg_type_typname_nsp_index" or constraint is None
             )
+            if constraint is None:
+                logger.debug(
+                    f"UniqueViolation constraint_name unavailable, assuming pg_type race. "
+                    f"Full error: {e}"
+                )

73-74: Use logger.exception for better tracebacks when re-raising.

Same as the DuplicateTable handler—use logger.exception to capture the full traceback.

Suggested fix
-            logger.exception(f"UniqueViolation error (constraint={constraint}): {e.pgerror}")
+            logger.exception(f"UniqueViolation error (constraint={constraint}): {e.pgerror}")

Wait, let me fix this:

-            logger.error(f"UniqueViolation error (constraint={constraint}): {e.pgerror}")
+            logger.exception(f"UniqueViolation error (constraint={constraint}): {e.pgerror}")
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between ed01126 and d830ef6.

📒 Files selected for processing (1)
  • unstract/connectors/src/unstract/connectors/databases/psycopg_handler.py
🧰 Additional context used
🪛 Ruff (0.14.10)
unstract/connectors/src/unstract/connectors/databases/psycopg_handler.py

55-55: Use logging.exception instead of logging.error

Replace with exception

(TRY400)


73-73: Use logging.exception instead of logging.error

Replace with exception

(TRY400)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (1)
unstract/connectors/src/unstract/connectors/databases/psycopg_handler.py (1)

18-23: LGTM!

Clean extraction of the constant and helper function. The case-insensitive matching via .upper() ensures SQL queries are properly detected regardless of case formatting.

@github-actions
Copy link
Contributor

Test Results

Summary
  • Runner Tests: 11 passed, 0 failed (11 total)
  • SDK1 Tests: 66 passed, 0 failed (66 total)

Runner Tests - Full Report
filepath function $$\textcolor{#23d18b}{\tt{passed}}$$ SUBTOTAL
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_logs}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_cleanup}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_cleanup\_skip}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_client\_init}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_get\_image\_exists}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_get\_image}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_get\_container\_run\_config}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_get\_container\_run\_config\_without\_mount}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_run\_container}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_get\_image\_for\_sidecar}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_sidecar\_container}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{TOTAL}}$$ $$\textcolor{#23d18b}{\tt{11}}$$ $$\textcolor{#23d18b}{\tt{11}}$$
SDK1 Tests - Full Report
filepath function $$\textcolor{#23d18b}{\tt{passed}}$$ SUBTOTAL
$$\textcolor{#23d18b}{\tt{tests/test\_platform.py}}$$ $$\textcolor{#23d18b}{\tt{TestPlatformHelperRetry.test\_success\_on\_first\_attempt}}$$ $$\textcolor{#23d18b}{\tt{2}}$$ $$\textcolor{#23d18b}{\tt{2}}$$
$$\textcolor{#23d18b}{\tt{tests/test\_platform.py}}$$ $$\textcolor{#23d18b}{\tt{TestPlatformHelperRetry.test\_retry\_on\_connection\_error}}$$ $$\textcolor{#23d18b}{\tt{2}}$$ $$\textcolor{#23d18b}{\tt{2}}$$
$$\textcolor{#23d18b}{\tt{tests/test\_platform.py}}$$ $$\textcolor{#23d18b}{\tt{TestPlatformHelperRetry.test\_non\_retryable\_http\_error}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/test\_platform.py}}$$ $$\textcolor{#23d18b}{\tt{TestPlatformHelperRetry.test\_retryable\_http\_errors}}$$ $$\textcolor{#23d18b}{\tt{3}}$$ $$\textcolor{#23d18b}{\tt{3}}$$
$$\textcolor{#23d18b}{\tt{tests/test\_platform.py}}$$ $$\textcolor{#23d18b}{\tt{TestPlatformHelperRetry.test\_post\_method\_retry}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/test\_platform.py}}$$ $$\textcolor{#23d18b}{\tt{TestPlatformHelperRetry.test\_retry\_logging}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/test\_prompt.py}}$$ $$\textcolor{#23d18b}{\tt{TestPromptToolRetry.test\_success\_on\_first\_attempt}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/test\_prompt.py}}$$ $$\textcolor{#23d18b}{\tt{TestPromptToolRetry.test\_retry\_on\_errors}}$$ $$\textcolor{#23d18b}{\tt{2}}$$ $$\textcolor{#23d18b}{\tt{2}}$$
$$\textcolor{#23d18b}{\tt{tests/test\_prompt.py}}$$ $$\textcolor{#23d18b}{\tt{TestPromptToolRetry.test\_wrapper\_methods\_retry}}$$ $$\textcolor{#23d18b}{\tt{4}}$$ $$\textcolor{#23d18b}{\tt{4}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestIsRetryableError.test\_connection\_error\_is\_retryable}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestIsRetryableError.test\_timeout\_is\_retryable}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestIsRetryableError.test\_http\_error\_retryable\_status\_codes}}$$ $$\textcolor{#23d18b}{\tt{3}}$$ $$\textcolor{#23d18b}{\tt{3}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestIsRetryableError.test\_http\_error\_non\_retryable\_status\_codes}}$$ $$\textcolor{#23d18b}{\tt{5}}$$ $$\textcolor{#23d18b}{\tt{5}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestIsRetryableError.test\_http\_error\_without\_response}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestIsRetryableError.test\_os\_error\_retryable\_errno}}$$ $$\textcolor{#23d18b}{\tt{5}}$$ $$\textcolor{#23d18b}{\tt{5}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestIsRetryableError.test\_os\_error\_non\_retryable\_errno}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestIsRetryableError.test\_other\_exception\_not\_retryable}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCalculateDelay.test\_exponential\_backoff\_without\_jitter}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCalculateDelay.test\_exponential\_backoff\_with\_jitter}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCalculateDelay.test\_max\_delay\_cap}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCalculateDelay.test\_max\_delay\_cap\_with\_jitter}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryWithExponentialBackoff.test\_successful\_call\_first\_attempt}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryWithExponentialBackoff.test\_retry\_after\_transient\_failure}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryWithExponentialBackoff.test\_max\_retries\_exceeded}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryWithExponentialBackoff.test\_max\_time\_exceeded}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryWithExponentialBackoff.test\_retry\_with\_custom\_predicate}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryWithExponentialBackoff.test\_no\_retry\_with\_predicate\_false}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryWithExponentialBackoff.test\_exception\_not\_in\_tuple\_not\_retried}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryWithExponentialBackoff.test\_delay\_would\_exceed\_max\_time}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_default\_configuration}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_environment\_variable\_configuration}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_invalid\_max\_retries}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_invalid\_max\_time}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_invalid\_base\_delay}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_invalid\_multiplier}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_jitter\_values}}$$ $$\textcolor{#23d18b}{\tt{2}}$$ $$\textcolor{#23d18b}{\tt{2}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_custom\_exceptions\_only}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_custom\_predicate\_only}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_both\_exceptions\_and\_predicate}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_exceptions\_match\_but\_predicate\_false}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestPreconfiguredDecorators.test\_retry\_platform\_service\_call\_exists}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestPreconfiguredDecorators.test\_retry\_prompt\_service\_call\_exists}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestPreconfiguredDecorators.test\_platform\_service\_decorator\_retries\_on\_connection\_error}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestPreconfiguredDecorators.test\_prompt\_service\_decorator\_retries\_on\_timeout}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryLogging.test\_warning\_logged\_on\_retry}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryLogging.test\_info\_logged\_on\_success\_after\_retry}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryLogging.test\_exception\_logged\_on\_giving\_up}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{TOTAL}}$$ $$\textcolor{#23d18b}{\tt{66}}$$ $$\textcolor{#23d18b}{\tt{66}}$$

@sonarqubecloud
Copy link

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.

4 participants