Skip to content

Fix: Queue filtering #298

Open
l-mansouri wants to merge 6 commits intomainfrom
queue-filtering-fix
Open

Fix: Queue filtering #298
l-mansouri wants to merge 6 commits intomainfrom
queue-filtering-fix

Conversation

@l-mansouri
Copy link
Collaborator

@l-mansouri l-mansouri commented Mar 11, 2026

Overview

This PR implements a fix for filtering by queue in cloudos job list

JIRA

Please add here as many related tasks this PR covers with its brief description, if more than one ticket

LP-105358

Changes

  • Refactors the queue filtering approach

Acceptance Criteria

Please add here as many scenarios as in the Story

Normally this acceptance criteria is tested in ADAPT workspace in PROD

What was happening before the fix Screenshot 2026-03-11 at 14 22 39
What happens after the fix Screenshot 2026-03-11 at 14 21 03

AZURE

CANNOT BE TESTED IN AZURE AS AZURE DO NOT HAVE AWS QUEUE


Note

Medium Risk
Changes pagination/stop conditions in get_job_list when --filter-queue is used, which can alter job listing results and request volume. Low blast radius but affects a frequently used CLI path and could surface edge-case pagination bugs.

Overview
Fixes cloudos job list --filter-queue so queue filtering happens during pagination rather than after a single fetched page, ensuring jobs are found even when early pages contain no matches.

This refactors get_job_list to resolve the queue name to an ID up front, apply the queue filter per page, and continue fetching additional pages in direct --page/--page-size mode until enough filtered results are collected or the API is exhausted. Version is bumped to 2.82.1 and the changelog documents the fix.

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

@l-mansouri l-mansouri changed the title Queue filtering fix Fix: Queue filtering Mar 11, 2026
Copy link

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

Bugbot Free Tier Details

Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: False "not batch" error after valid queue filtering
    • Removed the post-filter batch-environment validation so valid queue filters with zero matching jobs now correctly return an empty result instead of raising a false non-batch error.

Create PR

Or push these changes by commenting:

@cursor push ddf295dfc4
Preview (ddf295dfc4)
diff --git a/cloudos_cli/clos.py b/cloudos_cli/clos.py
--- a/cloudos_cli/clos.py
+++ b/cloudos_cli/clos.py
@@ -1249,16 +1249,6 @@
         if use_pagination_mode and target_job_count != 'all' and isinstance(target_job_count, int) and target_job_count > 0:
             all_jobs = all_jobs[:target_job_count]
 
-        # --- Validate queue filtering (check if environment is batch) ---
-        if filter_queue:
-            # Check if any jobs actually are batch jobs (non-batch jobs won't have jobQueue)
-            batch_jobs = [job for job in all_jobs if job.get("batch", {})]
-            if not batch_jobs:
-                # No batch jobs found - verify environment actually has batch capability
-                # by checking if any batch jobs exist in workspace at all
-                # Note: This is a best-effort check with the current page being fetched
-                raise ValueError(f"The environment is not a batch environment so queues do not exist. Please remove the --filter-queue option.")
-
         return {'jobs': all_jobs, 'pagination_metadata': last_pagination_metadata}
 
     @staticmethod

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

Copy link

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

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

@cursor
Copy link

cursor bot commented Mar 11, 2026

You have run out of free Bugbot PR reviews for this billing cycle. This will reset on April 6.

To receive reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

@l-mansouri l-mansouri marked this pull request as draft March 12, 2026 08:34
@l-mansouri l-mansouri marked this pull request as ready for review March 12, 2026 08:34
@danielboloc
Copy link
Collaborator

thanks @l-mansouri

The only thing that is confusing is the pagination data at the bottom "Showing 10 of 2037 total jobs | Page 115 of 204", but there is no way to navigate through the pages.
image

I propose to unify this as the other tables , where we have that info but we can navigate it with "n = next, p = prev, q = quit"
image

I am tagging @dapineyro since is out of the scope of this task, to keep in mind for future tickets:

  • Updating pagination for job list to have user controls as other tables "n = next, p = prev, q = quit"


for queue in queues:
if queue.get("label") == filter_queue or queue.get("name") == filter_queue:
queue_id = queue.get("id") or queue.get("_id")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you try if as in the case of workflows params["workflow.id"] = workflow_id would work when adding the queue name since the response is"batch":{"enabled":true,"jobQueue":"69b2859f403797abd4686fb6"} for example, to do:

params["batch.jobQueue"] = queue_id

this might simplify the logic a lot

Copy link
Collaborator Author

@l-mansouri l-mansouri Mar 13, 2026

Choose a reason for hiding this comment

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

I don't think I understand what you mean. could you explain it more?
I am confused because params["batch.jobQueue"] = queue_id is not present here.
Queue filtering can't happen on the server (it's not even in the ui), so we have to get the job details (that only contain the queue id) and compare them to the requested queue name.
In this if I am converting the queue name to id. Then I am comparing it to the one of jobs, further down in the code like so

        if filter_queue and queue_id:
                filtered_jobs = []
                for job in page_jobs:
                    job_queue = job.get("batch", {}).get("jobQueue")
                    # jobQueue can be a string ID or a dict with {"id": "...", "name": "..."}
                    job_queue_id = job_queue.get("id") if isinstance(job_queue, dict) else job_queue
                    if job_queue_id == queue_id:
                        filtered_jobs.append(job)
                page_jobs = filtered_jobs

            all_jobs.extend(page_jobs)

            # Check stopping conditions based on mode
            if use_pagination_mode:
                # In pagination mode (last_n_jobs), continue until we have enough jobs (after filtering)
                if target_job_count != 'all' and len(all_jobs) >= target_job_count:
                    break
            else:
                # In direct mode (page/page_size):
                # - Without filter_queue: stop after 1 page
                # - With filter_queue: continue until we have page_size filtered results
                if not filter_queue or len(all_jobs) >= current_page_size:
                    break

            # Check if we reached the last page (fewer jobs than requested page size)
            raw_page_jobs = content.get('jobs', [])
            if len(raw_page_jobs) < params["limit"]:
                break  # Last page

            current_page += 1

        # --- Apply limit after all filtering ---
        if use_pagination_mode and target_job_count != 'all' and isinstance(target_job_count, int) and target_job_count > 0:
            all_jobs = all_jobs[:target_job_count]

the only 2 line I can simplify are

                     job_queue = job.get("batch", {}).get("jobQueue")
                    # jobQueue can be a string ID or a dict with {"id": "...", "name": "..."}
                    job_queue_id = job_queue.get("id") if isinstance(job_queue, dict) else job_queue

they could be simplified like

job_queue_id = job.get("batch", {}).get("jobQueue")

by removing the case in which the jobqueue is like it is in job details where it's a dictionary, as currently that is not the case here. However, it does not simplify much the logic

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