Skip to content

Conversation

@vishnuszipstack
Copy link
Contributor

@vishnuszipstack vishnuszipstack commented Sep 23, 2025

What

  • HITL Enhancements OSS PR

Why

  • HITL Enhancements

How

  • More details available in cloud PR

Can this PR break any existing features. If yes, please list possible items. If no, please explain why. (PS: Admins do not merge the PR without this section filled)

  • No

Database Migrations

Env Config

Relevant Docs

Related Issues or PRs

Dependencies Versions

Notes on Testing

Screenshots

Checklist

I have read and understood the Contribution Guidelines.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 23, 2025

Summary by CodeRabbit

  • New Features
    • Added Human-In-The-Loop (HITL) workflow support to enable manual review capabilities within automated processes.
    • Enhanced queue routing with organization-level management for improved workflow distribution.
    • Added file storage configuration for HITL-specific files with MinIO integration.

Walkthrough

Adds HITL-aware queue selection and enqueueing: destination resolves organization_id to request HITL-capable queues; QueueUtils gains HITL routing, lazy connector imports/caching, and explicit HITL queue instantiation; filesystem adds HITL_FILES storage type and credential mapping; sample env exposes HITL storage credentials.

Changes

Cohort / File(s) Summary
HITL-aware enqueue changes
backend/workflow_manager/endpoint_v2/destination.py
Destination now obtains organization_id from UserContext, requests a HITL-enabled queue via QueueUtils.get_queue_inst({"use_hitl_backend": True, "organization_id": organization_id}), and includes organization_id in packet and regular enqueue calls. Logs updated to include organization_id and TTL where applicable.
HITL queue selection & connectors
backend/workflow_manager/endpoint_v2/queue_utils.py
Adds HITL flow: class-level _hitl_connectors cache, get_hitl_queue_inst(backend, connector_settings) public method, and _import_hitl_connector(connector_name) private loader performing lazy dynamic imports for PostgreSQL/Hybrid HITL connectors. Redis HITL delegates to non-HITL path. Structured error handling and logging for missing/unknown HITL backends.
Filesystem HITL storage & env
unstract/filesystem/src/unstract/filesystem/file_storage_types.py, unstract/filesystem/src/unstract/filesystem/file_storage_config.py, backend/sample.env
Adds FileStorageType.HITL_FILES, maps it to StorageType.SHARED_TEMPORARY, adds HITL_FILES_FILE_STORAGE_CREDENTIALS to credentials→env mapping, and appends example HITL_FILES_FILE_STORAGE_CREDENTIALS to sample environment file.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client
  participant Destination as endpoint_v2.destination
  participant QueueUtils
  participant HITLConnector as HITL Connector
  participant Queue as Queue Instance

  Client->>Destination: enqueue request
  Destination->>Destination: resolve organization_id
  Destination->>QueueUtils: get_queue_inst({use_hitl_backend: true, organization_id})
  alt HITL path
    QueueUtils->>QueueUtils: get_hitl_queue_inst(backend, settings)
    alt backend == PostgreSQL or Hybrid
      QueueUtils->>QueueUtils: _import_hitl_connector(name)
      QueueUtils->>HITLConnector: instantiate(settings)
      HITLConnector-->>QueueUtils: return Queue Instance
    else backend == Redis
      QueueUtils->>QueueUtils: clear HITL flag, delegate to standard connector
    else unknown/missing
      QueueUtils-->>Destination: raise UnstractQueueException
    end
  else non-HITL path
    QueueUtils->>QueueUtils: standard get_queue_inst flow
  end
  QueueUtils-->>Destination: Queue Instance
  Destination->>Queue: enqueue(payload, ttl_seconds?, actor_id=None, organization_id)
  Queue-->>Destination: enqueue result
  Destination-->>Client: acknowledgement
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay extra attention to:
    • queue_utils.get_hitl_queue_inst dynamic import, instantiation, and error mappings.
    • destination.py changes ensuring organization_id is consistently propagated to enqueue calls and logs.
    • New enum/storage mapping entries for compatibility and any migration/usage sites of FileStorageType.

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description Check ❓ Inconclusive The PR description is significantly incomplete and vague. While it follows the template structure, most sections contain minimal or generic content: "What" and "Why" sections simply repeat "HITL Enhancements" without meaningful detail, and the "How" section delegates to an external cloud PR rather than explaining the actual implementation approach. Most critically, the "Env Config" section is left blank despite the raw summary clearly showing new environment variable additions (HITL_FILES_FILE_STORAGE_CREDENTIALS) that must be documented for deployment. This omission, combined with the generic content elsewhere, makes it difficult for reviewers to understand the scope and implications of these changes. The description should be substantially improved before merging. Specifically: (1) fill the "Env Config" section with documentation of the HITL_FILES_FILE_STORAGE_CREDENTIALS environment variable and its purpose, (2) expand the "What" section to explain the specific HITL enhancements being implemented (new connectors, queue routing changes, etc.), (3) expand the "Why" section with business or technical motivation, and (4) provide a meaningful "How" section that summarizes the implementation approach rather than redirecting to another PR.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The PR title "UN-2663 [FEAT] moving away from redis hitl file handling improvements" is clearly and specifically related to the main changes in the pull request. The raw summary confirms that the changeset implements HITL enhancements, including new HITL connector support, modified queue handling, and updated file storage configuration for HITL_FILES. The title accurately conveys that this PR is focused on improving HITL file handling with a shift away from Redis-based approaches. While the title includes a ticket number and feature tag (common conventions), it remains concise and provides meaningful information for developers scanning the commit history.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch UN-2663-moving-away-from-redis-hitl-file-handling-improvements

📜 Recent review details

Configuration used: CodeRabbit 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 fd17def and f2c6901.

📒 Files selected for processing (2)
  • backend/sample.env (1 hunks)
  • backend/workflow_manager/endpoint_v2/destination.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • backend/workflow_manager/endpoint_v2/destination.py
  • backend/sample.env

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: 2

🧹 Nitpick comments (4)
unstract/filesystem/src/unstract/filesystem/file_storage_config.py (1)

31-32: Confirm SHARED_TEMPORARY aligns with HITL data handling.

If HITL artifacts may include PII, confirm SHARED_TEMPORARY meets isolation, retention, and encryption expectations; otherwise consider a dedicated storage tier/bucket/namespace.

backend/workflow_manager/endpoint_v2/queue_utils.py (3)

28-41: Avoid mutable default for connector_settings

Use None default and initialize inside to satisfy linters and prevent shared state.

-    def get_queue_inst(connector_settings: dict[str, Any] = {}) -> UnstractQueue:
+    def get_queue_inst(connector_settings: dict[str, Any] | None = None) -> UnstractQueue:
+        if connector_settings is None:
+            connector_settings = {}
         """Get queue connector instance based on configuration.

53-56: Avoid mutable default for connector_settings (HITL path)

Same fix for get_hitl_queue_inst.

-    def get_hitl_queue_inst(
-        backend: str, connector_settings: dict[str, Any] = {}
-    ) -> UnstractQueue:
+    def get_hitl_queue_inst(
+        backend: str, connector_settings: dict[str, Any] | None = None
+    ) -> UnstractQueue:
+        if connector_settings is None:
+            connector_settings = {}

95-109: Prefer logger.exception and preserve traceback with from e

Improves observability and complies with linter hints.

-        except ImportError as e:
-            logger.error(
-                f"HITL queue backend '{backend}' not available: {e}. "
-                f"Make sure 'pluggable_apps.manual_review_v2' is installed and configured."
-            )
-            raise UnstractQueueException(
-                detail=f"HITL queue backend '{backend}' not available. "
-                f"Please install the manual_review_v2 app or use 'redis' backend."
-            )
-        except Exception as e:
-            logger.error(f"Failed to initialize HITL queue backend '{backend}': {e}")
-            raise UnstractQueueException(
-                detail=f"Failed to initialize HITL queue backend '{backend}': {str(e)}"
-            )
+        except ImportError as e:
+            logger.exception(
+                "HITL queue backend '%s' not available: %s. Make sure 'pluggable_apps.manual_review_v2' is installed and configured.",
+                backend, e
+            )
+            raise UnstractQueueException(
+                detail=f"HITL queue backend '{backend}' not available. "
+                f"Please install the manual_review_v2 app or use 'redis' backend."
+            ) from e
+        except Exception as e:
+            logger.exception("Failed to initialize HITL queue backend '%s': %s", backend, e)
+            raise UnstractQueueException(
+                detail=f"Failed to initialize HITL queue backend '{backend}': {str(e)}"
+            ) from e
📜 Review details

Configuration used: CodeRabbit 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 51bea4e and c41d334.

📒 Files selected for processing (4)
  • backend/workflow_manager/endpoint_v2/destination.py (2 hunks)
  • backend/workflow_manager/endpoint_v2/queue_utils.py (4 hunks)
  • unstract/filesystem/src/unstract/filesystem/file_storage_config.py (1 hunks)
  • unstract/filesystem/src/unstract/filesystem/file_storage_types.py (1 hunks)
🧰 Additional context used
🪛 Ruff (0.13.1)
backend/workflow_manager/endpoint_v2/queue_utils.py

54-54: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)


96-99: Use logging.exception instead of logging.error

Replace with exception

(TRY400)


100-103: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


104-104: Do not catch blind exception: Exception

(BLE001)


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

Replace with exception

(TRY400)


106-108: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


107-107: Use explicit conversion flag

Replace with conversion flag

(RUF010)


141-143: Avoid specifying long messages outside the exception class

(TRY003)


147-149: Avoid specifying long messages outside the exception class

(TRY003)

⏰ 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 (2)
unstract/filesystem/src/unstract/filesystem/file_storage_types.py (1)

7-7: Add brief usage note or doc where this enum is documented.

LGTM. Please ensure HITL_FILES is referenced in any docs/samples that enumerate FileStorageType values.

backend/workflow_manager/endpoint_v2/destination.py (1)

802-816: Verify HITL queue connector API supports enqueue_with_ttl; prefer self.organization_id

  • UnstractQueue does not declare enqueue_with_ttl and the repo has no implementations — confirm pluggable HITL connectors (HybridQueue/PostgreSQLQueue) expose enqueue_with_ttl(queue_name, message, ttl_seconds=None, actor_id=None) or add the method/guard the call to avoid AttributeError.
  • Replace re-fetch of org id with self.organization_id in backend/workflow_manager/endpoint_v2/destination.py (occurrences near lines ~803 and ~864):
-            organization_id = UserContext.get_organization_identifier()
+            organization_id = self.organization_id

@vishnuszipstack vishnuszipstack changed the title Un 2663 moving away from redis hitl file handling improvements UN-2663 [FEAT] moving away from redis hitl file handling improvements Sep 23, 2025

if is_hitl:
# Use HITL-specific queue backend
hitl_backend = getattr(settings, "HITL_QUEUE_BACKEND", "hybrid")
Copy link
Contributor

Choose a reason for hiding this comment

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

NIT: Specify the default value for this setting in the config file itself and directly use the setting here

Comment on lines +95 to +108
except ImportError as e:
logger.error(
f"HITL queue backend '{backend}' not available: {e}. "
f"Make sure 'pluggable_apps.manual_review_v2' is installed and configured."
)
raise UnstractQueueException(
detail=f"HITL queue backend '{backend}' not available. "
f"Please install the manual_review_v2 app or use 'redis' backend."
)
except Exception as e:
logger.error(f"Failed to initialize HITL queue backend '{backend}': {e}")
raise UnstractQueueException(
detail=f"Failed to initialize HITL queue backend '{backend}': {str(e)}"
)
Copy link
Contributor

Choose a reason for hiding this comment

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

NIT: Might not be necessary to log the error here since the middleware takes care of it already in case of an error. Also in the given pattern, we print the pythonic error and we might risk showing it to the user

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

🧹 Nitpick comments (1)
backend/workflow_manager/endpoint_v2/queue_utils.py (1)

54-78: Avoid mutable default for connector_settings

Using {} as a default argument means every call without an explicit settings dict shares the same object, which can lead to surprising cross-call mutations if a connector modifies the dict. Please default to None and instantiate inside the function.

-        backend: str, connector_settings: dict[str, Any] = {}
+        backend: str, connector_settings: dict[str, Any] | None = None
     ) -> UnstractQueue:
@@
-        if backend == "redis":
+        connector_settings = connector_settings or {}
+        if backend == "redis":
             # Strip HITL flag to force default (non-HITL) connector path
             non_hitl_settings = dict(connector_settings)

Based on static analysis hints.

📜 Review details

Configuration used: CodeRabbit 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 c41d334 and 047e601.

📒 Files selected for processing (2)
  • backend/sample.env (1 hunks)
  • backend/workflow_manager/endpoint_v2/queue_utils.py (3 hunks)
🧰 Additional context used
🪛 Ruff (0.13.1)
backend/workflow_manager/endpoint_v2/queue_utils.py

25-25: Mutable class attributes should be annotated with typing.ClassVar

(RUF012)


28-28: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)


54-54: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)


99-102: Use logging.exception instead of logging.error

Replace with exception

(TRY400)


103-106: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


107-107: Do not catch blind exception: Exception

(BLE001)


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

Replace with exception

(TRY400)


109-111: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


110-110: Use explicit conversion flag

Replace with conversion flag

(RUF010)


142-144: Avoid specifying long messages outside the exception class

(TRY003)


148-150: Avoid specifying long messages outside the exception class

(TRY003)

⏰ 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)
backend/sample.env (1)

204-204: LGTM: HITL storage credentials sample entry

Thanks for wiring up the sample credentials; this keeps the sample env aligned with the new HITL_FILES storage configuration.

Comment on lines +73 to +97
if backend == "redis":
# Strip HITL flag to force default (non-HITL) connector path
non_hitl_settings = dict(connector_settings)
non_hitl_settings.pop("use_hitl_backend", None)
return QueueUtils.get_queue_inst(non_hitl_settings)

# For PostgreSQL and Hybrid backends, try dynamic imports
try:
if backend == "postgresql":
connector_class = QueueUtils._import_hitl_connector("PostgreSQLQueue")
return connector_class(connector_settings)

elif backend == "hybrid":
connector_class = QueueUtils._import_hitl_connector("HybridQueue")
return connector_class(connector_settings)

else:
logger.warning(
f"Unknown HITL queue backend '{backend}'. "
f"Valid options: postgresql, hybrid, redis. "
f"Attempting fallback to hybrid."
)
connector_class = QueueUtils._import_hitl_connector("HybridQueue")
return connector_class(connector_settings)

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Normalize HITL backend selection to avoid wrong connector path

HITL_QUEUE_BACKEND comes from environment configuration, so values like REDIS, Redis, or PostgreSQL are plausible. Because the current check is case-sensitive, anything other than exact lowercase redis/postgresql/hybrid slides into the “unknown” branch, skipping the Redis fallback and, in many deployments, raising an exception instead of enqueueing. Please normalize the backend string (e.g., normalized_backend = (backend or "").lower()) before branching so all common spellings hit the intended code path.

-        if backend == "redis":
+        normalized_backend = (backend or "").lower()
+        if normalized_backend == "redis":
             # Strip HITL flag to force default (non-HITL) connector path
             non_hitl_settings = dict(connector_settings)
             non_hitl_settings.pop("use_hitl_backend", None)
             return QueueUtils.get_queue_inst(non_hitl_settings)
 
         # For PostgreSQL and Hybrid backends, try dynamic imports
         try:
-            if backend == "postgresql":
+            if normalized_backend == "postgresql":
                 connector_class = QueueUtils._import_hitl_connector("PostgreSQLQueue")
                 return connector_class(connector_settings)
 
-            elif backend == "hybrid":
+            elif normalized_backend == "hybrid":
                 connector_class = QueueUtils._import_hitl_connector("HybridQueue")
                 return connector_class(connector_settings)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if backend == "redis":
# Strip HITL flag to force default (non-HITL) connector path
non_hitl_settings = dict(connector_settings)
non_hitl_settings.pop("use_hitl_backend", None)
return QueueUtils.get_queue_inst(non_hitl_settings)
# For PostgreSQL and Hybrid backends, try dynamic imports
try:
if backend == "postgresql":
connector_class = QueueUtils._import_hitl_connector("PostgreSQLQueue")
return connector_class(connector_settings)
elif backend == "hybrid":
connector_class = QueueUtils._import_hitl_connector("HybridQueue")
return connector_class(connector_settings)
else:
logger.warning(
f"Unknown HITL queue backend '{backend}'. "
f"Valid options: postgresql, hybrid, redis. "
f"Attempting fallback to hybrid."
)
connector_class = QueueUtils._import_hitl_connector("HybridQueue")
return connector_class(connector_settings)
normalized_backend = (backend or "").lower()
if normalized_backend == "redis":
# Strip HITL flag to force default (non-HITL) connector path
non_hitl_settings = dict(connector_settings)
non_hitl_settings.pop("use_hitl_backend", None)
return QueueUtils.get_queue_inst(non_hitl_settings)
# For PostgreSQL and Hybrid backends, try dynamic imports
try:
if normalized_backend == "postgresql":
connector_class = QueueUtils._import_hitl_connector("PostgreSQLQueue")
return connector_class(connector_settings)
elif normalized_backend == "hybrid":
connector_class = QueueUtils._import_hitl_connector("HybridQueue")
return connector_class(connector_settings)
else:
logger.warning(
f"Unknown HITL queue backend '{backend}'. "
f"Valid options: postgresql, hybrid, redis. "
f"Attempting fallback to hybrid."
)
connector_class = QueueUtils._import_hitl_connector("HybridQueue")
return connector_class(connector_settings)
🤖 Prompt for AI Agents
In backend/workflow_manager/endpoint_v2/queue_utils.py around lines 73 to 97,
the branch logic uses case-sensitive backend string checks causing values like
"Redis" or "PostgreSQL" to fall through to the unknown branch; fix by
normalizing the incoming backend value first (e.g., normalized_backend =
(backend or "").lower()) and then use normalized_backend in all subsequent
comparisons and logging, ensuring the Redis/PostgreSQL/Hybrid branches and the
fallback behave correctly even when env vars differ in case.

Copy link
Contributor

@chandrasekharan-zipstack chandrasekharan-zipstack left a comment

Choose a reason for hiding this comment

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

NIT comments can be resolved later

UnstractQueueException: When HITL connectors are not available
"""
# For Redis backend, use default connector
if backend == "redis":
Copy link
Contributor

Choose a reason for hiding this comment

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

NIT: @vishnuszipstack can we keep this as a constant to keep uniformity in codebase.

Copy link
Contributor

@jaseemjaskp jaseemjaskp left a comment

Choose a reason for hiding this comment

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

LGTM

…dling-improvements

Signed-off-by: vishnuszipstack <117254672+vishnuszipstack@users.noreply.github.com>
@github-actions
Copy link
Contributor

github-actions bot commented Oct 6, 2025

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}}$$

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: 2

🧹 Nitpick comments (1)
backend/sample.env (1)

204-204: Consider adding a documentation comment.

The new HITL_FILES_FILE_STORAGE_CREDENTIALS environment variable lacks an explanatory comment. Adding a brief comment (similar to those for other sections like "X2Text Service" or "Prompt Studio") would improve clarity for developers.

Example:

+# HITL (Human-In-The-Loop) Files Storage
 HITL_FILES_FILE_STORAGE_CREDENTIALS='{"provider": "minio", "credentials": {"endpoint_url": "http://unstract-minio:9000", "key": "minio", "secret": "minio123"}}'

Operational note: While reusing the same MinIO instance and credentials is appropriate for this sample configuration, production deployments should consider isolating HITL file storage with separate credentials or dedicated storage to enhance security boundaries and enable independent scaling/lifecycle management.

📜 Review details

Configuration used: CodeRabbit 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 b585759 and fd17def.

📒 Files selected for processing (2)
  • backend/sample.env (1 hunks)
  • backend/workflow_manager/endpoint_v2/destination.py (2 hunks)
⏰ 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

Comment on lines 873 to 887
# Get organization_id for proper HITL queue filtering
organization_id = UserContext.get_organization_identifier()
conn = QueueUtils.get_queue_inst(
{"use_hitl_backend": True, "organization_id": organization_id}
)
# API deployments don't have TTL, use system actor
conn.enqueue_with_ttl(
queue_name=q_name,
message=queue_result_json,
ttl_seconds=None, # No TTL for API deployments
actor_id=None, # System-initiated enqueue
)
logger.info(
f"Pushed {file_name} to queue {q_name} with organization_id {organization_id}"
)
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Use cached self.organization_id instead of fetching again.

The organization_id is already fetched and stored in self.organization_id at line 79 during initialization. Fetching it again here is redundant and could theoretically lead to inconsistency if the user context changes between initialization and this call.

Apply this diff:

-            # Get organization_id for proper HITL queue filtering
-            organization_id = UserContext.get_organization_identifier()
             conn = QueueUtils.get_queue_inst(
-                {"use_hitl_backend": True, "organization_id": organization_id}
+                {"use_hitl_backend": True, "organization_id": self.organization_id}
             )
             # API deployments don't have TTL, use system actor
             conn.enqueue_with_ttl(
                 queue_name=q_name,
                 message=queue_result_json,
                 ttl_seconds=None,  # No TTL for API deployments
                 actor_id=None,  # System-initiated enqueue
             )
             logger.info(
-                f"Pushed {file_name} to queue {q_name} with organization_id {organization_id}"
+                f"Pushed {file_name} to queue {q_name} with organization_id {self.organization_id}"
             )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Get organization_id for proper HITL queue filtering
organization_id = UserContext.get_organization_identifier()
conn = QueueUtils.get_queue_inst(
{"use_hitl_backend": True, "organization_id": organization_id}
)
# API deployments don't have TTL, use system actor
conn.enqueue_with_ttl(
queue_name=q_name,
message=queue_result_json,
ttl_seconds=None, # No TTL for API deployments
actor_id=None, # System-initiated enqueue
)
logger.info(
f"Pushed {file_name} to queue {q_name} with organization_id {organization_id}"
)
conn = QueueUtils.get_queue_inst(
{"use_hitl_backend": True, "organization_id": self.organization_id}
)
# API deployments don't have TTL, use system actor
conn.enqueue_with_ttl(
queue_name=q_name,
message=queue_result_json,
ttl_seconds=None, # No TTL for API deployments
actor_id=None, # System-initiated enqueue
)
logger.info(
f"Pushed {file_name} to queue {q_name} with organization_id {self.organization_id}"
)
🤖 Prompt for AI Agents
In backend/workflow_manager/endpoint_v2/destination.py around lines 873 to 887,
the code redundantly calls UserContext.get_organization_identifier() even though
self.organization_id was set at initialization; replace that call with using
self.organization_id (ensure it is used directly when building the
QueueUtils.get_queue_inst call and in the log message) so the method uses the
cached organization identifier rather than re-fetching from UserContext.

Comment on lines 937 to 952
# Get organization_id for proper HITL queue filtering
organization_id = UserContext.get_organization_identifier()
conn = QueueUtils.get_queue_inst(
{"use_hitl_backend": True, "organization_id": organization_id}
)
# Use TTL from workflow settings, system actor for workflow enqueue
ttl_seconds = queue_result_obj.ttl_seconds

conn.enqueue_with_ttl(
queue_name=q_name, message=queue_result_json, ttl_seconds=ttl_seconds
queue_name=q_name,
message=queue_result_json,
ttl_seconds=ttl_seconds,
actor_id=None, # System-initiated enqueue
)
logger.info(
f"Pushed {file_name} to queue {q_name} with organization_id {organization_id} and TTL {ttl_seconds}"
)
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Use cached self.organization_id instead of fetching again.

Same issue as in the API path above. The organization_id is already available as self.organization_id from initialization (line 79) and should be reused here.

Apply this diff:

-            # Get organization_id for proper HITL queue filtering
-            organization_id = UserContext.get_organization_identifier()
             conn = QueueUtils.get_queue_inst(
-                {"use_hitl_backend": True, "organization_id": organization_id}
+                {"use_hitl_backend": True, "organization_id": self.organization_id}
             )
             # Use TTL from workflow settings, system actor for workflow enqueue
             ttl_seconds = queue_result_obj.ttl_seconds
             conn.enqueue_with_ttl(
                 queue_name=q_name,
                 message=queue_result_json,
                 ttl_seconds=ttl_seconds,
                 actor_id=None,  # System-initiated enqueue
             )
             logger.info(
-                f"Pushed {file_name} to queue {q_name} with organization_id {organization_id} and TTL {ttl_seconds}"
+                f"Pushed {file_name} to queue {q_name} with organization_id {self.organization_id} and TTL {ttl_seconds}"
             )
🤖 Prompt for AI Agents
In backend/workflow_manager/endpoint_v2/destination.py around lines 937 to 952,
the code re-fetches the organization id via
UserContext.get_organization_identifier() even though self.organization_id was
set at initialization; replace the local call and assign organization_id =
self.organization_id (or use self.organization_id directly) when building the
QueueUtils.get_queue_inst call and in the log message so the cached value is
reused and the extra context lookup is removed.

@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.

6 participants