Skip to content

Conversation

@ono-max
Copy link
Contributor

@ono-max ono-max commented Jan 21, 2025

Summary

  • New Features
    • Added a --non-blocking option to the subset command
    • Introduced ability to request a subset without waiting for a response in observation mode
$ find tests -name "test_*.py" | grep -v tests/data | /Users/ono-max/.local/share/virtualenvs/cli-tPknK2Me/bin/launchable subset --target 80% --observation --non-blocking file
The subset was requested in non-blocking mode.

@Konboi I've implemented this feature based on your suggestion. Can you review it? Thank you.

Summary by CodeRabbit

  • New Features
    • Added a non-blocking option for the subset command.
    • Enables asynchronous subset request processing.
  • Bug Fixes
    • Improved error handling for non-blocking mode.
  • Documentation
    • Updated command-line help text for the subset command, including corrections to typos.

@ono-max ono-max requested a review from Konboi January 21, 2025 06:35
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 21, 2025

Walkthrough

The pull request introduces a new --non-blocking option for the subset command in Launchable's CLI. This feature allows users to request a subset without waiting for the response when in observation mode. The implementation uses multiprocessing to handle subset requests asynchronously, with added error handling to ensure the option is used correctly and providing more flexible test subset generation.

Changes

File Change Summary
launchable/commands/subset.py - Added --non-blocking command-line option
- Introduced subset_request() helper function
- Implemented async subset request using multiprocessing.Process
- Updated error handling for non-blocking mode

Sequence Diagram

sequenceDiagram
    participant CLI as Launchable CLI
    participant Process as Subset Process
    participant API as Launchable API
    
    alt Non-Blocking Mode
        CLI->>Process: Start Async Subset Request
        Process->>API: Request Test Subset
        Process-->>CLI: Immediate Return
    else Blocking Mode
        CLI->>API: Synchronous Subset Request
        API-->>CLI: Return Test Subset
    end
Loading

Poem

🐰 A Rabbit's Subset Ballad 🧪
With non-blocking flair, I hop and spin,
Async requests, a new journey begins!
No more waiting, tests fly free,
Multiprocessing magic, just for thee!
Launchable's speed, now swift and bright! 🚀

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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)
launchable/commands/subset.py (1)

521-527: Consider enhancing non-blocking mode with status tracking.

The current implementation could benefit from additional features to make it more practical:

  1. Add a command to list ongoing non-blocking subset requests
  2. Add a command to check the status of a specific request
  3. Implement a simple status tracking mechanism using the metadata directory

Example implementation approach:

  1. Store request metadata (timestamp, session_id, process_id) in a JSON file
  2. Add subset list-requests command to show ongoing requests
  3. Add subset request-status <request_id> command to check specific requests
  4. Implement automatic cleanup of old request metadata

Would you like me to provide a detailed implementation proposal for these enhancements?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d6ba371 and acd5896.

📒 Files selected for processing (1)
  • launchable/commands/subset.py (6 hunks)
🧰 Additional context used
🪛 GitHub Actions: Python package
launchable/commands/subset.py

[error] 637-637: "dict" is not subscriptable, use "typing.Dict" instead

🔇 Additional comments (2)
launchable/commands/subset.py (2)

135-143: LGTM! Well-documented CLI option.

The --non-blocking option is implemented consistently with other options, and the help text clearly explains its purpose and limitations.


237-249: LGTM! Proper validation of non-blocking mode.

The code correctly validates that --non-blocking is only used with --observation mode, with appropriate error handling and user feedback.

Comment on lines 637 to 638
def subset_request(client: LaunchableClient, timeout: Tuple[int, int], payload: dict[str, Any]):
return client.request("post", "subset", timeout=timeout, payload=payload, compress=True)
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

Fix type annotation to use typing.Dict.

The pipeline failure indicates that dict is not subscriptable. Use typing.Dict instead.

Apply this fix:

-def subset_request(client: LaunchableClient, timeout: Tuple[int, int], payload: dict[str, Any]):
+def subset_request(client: LaunchableClient, timeout: Tuple[int, int], payload: Dict[str, Any]):
     return client.request("post", "subset", timeout=timeout, payload=payload, compress=True)
📝 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
def subset_request(client: LaunchableClient, timeout: Tuple[int, int], payload: dict[str, Any]):
return client.request("post", "subset", timeout=timeout, payload=payload, compress=True)
def subset_request(client: LaunchableClient, timeout: Tuple[int, int], payload: Dict[str, Any]):
return client.request("post", "subset", timeout=timeout, payload=payload, compress=True)
🧰 Tools
🪛 GitHub Actions: Python package

[error] 637-637: "dict" is not subscriptable, use "typing.Dict" instead

Comment on lines 521 to 527
if is_non_blocking:
# Create a new process for requesting a subset.
process = Process(target=subset_request, args=(client, timeout, payload))
process.start()
click.echo("The subset was requested in non-blocking mode.")
return

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

Add process error handling and cleanup.

The current implementation of non-blocking mode has several potential issues:

  1. No error handling for process creation/start failures
  2. No cleanup of zombie processes
  3. No way to track the status of the subset request

Consider implementing the following improvements:

 if is_non_blocking:
+    try:
         # Create a new process for requesting a subset.
-        process = Process(target=subset_request, args=(client, timeout, payload))
-        process.start()
+        process = Process(target=subset_request, args=(client, timeout, payload), daemon=True)
+        process.start()
+        # Store the process ID for potential future use
+        with open(os.path.join(app.get_metadata_dir(), f"subset_process_{session_id}.pid"), "w") as f:
+            f.write(str(process.pid))
+    except Exception as e:
+        msg = f"Failed to start non-blocking subset request: {str(e)}"
+        click.echo(click.style(msg, fg="red"), err=True)
+        tracking_client.send_error_event(
+            event_name=Tracking.ErrorEvent.INTERNAL_CLI_ERROR,
+            stack_trace=str(e),
+        )
+        sys.exit(1)
     click.echo("The subset was requested in non-blocking mode.")
     return

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Contributor

@Konboi Konboi left a comment

Choose a reason for hiding this comment

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

I asked a question about the specifications on the project page.

@ono-max
Copy link
Contributor Author

ono-max commented Jan 21, 2025

@Konboi

I fixed code based on your review. Thanks!

$ find tests -name "test_*.py" | grep -v tests/data | /Users/ono-max/.local/share/virtualenvs/cli-tPknK2Me/bin/launchable subset --target 80% --observation --non-blocking file
The subset was requested in non-blocking mode.
tests/test_version.py
tests/test_testpath.py
tests/test_plugin.py
tests/test_session.py
tests/utils/test_git_log_parser.py
tests/utils/test_link.py
tests/utils/test_gzipgen.py
tests/utils/test_authentication.py
tests/utils/test_http_client.py
tests/utils/test_click.py
tests/utils/test_file_name_pattern.py
tests/utils/test_glob.py
tests/utils/test_logger.py
tests/test_cli_test_case.py
tests/commands/test_subset.py
tests/commands/inspect/test_subset.py
tests/commands/inspect/test_tests.py
tests/commands/test_helper.py
tests/commands/record/test_session.py
tests/commands/record/test_attachment.py
tests/commands/record/test_tests.py
tests/commands/record/test_build.py
tests/commands/record/test_commit.py
tests/commands/test_verify.py
tests/commands/test_split_subset.py
tests/commands/test_api_error.py
tests/test_runners/test_ctest.py
tests/test_runners/test_gradle.py
tests/test_runners/test_cucumber.py
tests/test_runners/test_pytest.py
tests/test_runners/test_ant.py
tests/test_runners/test_jest.py
tests/test_runners/test_prove.py
tests/test_runners/test_bazel.py
tests/test_runners/test_go_test.py
tests/test_runners/test_minitest.py
tests/test_runners/test_robot.py
tests/test_runners/test_nunit.py
tests/test_runners/test_maven.py
tests/test_runners/test_dotnet.py
tests/test_runners/test_googletest.py
tests/test_runners/test_raw.py
tests/test_runners/test_behave.py
tests/test_runners/test_adb.py
tests/test_runners/test_cypress.py
tests/test_runners/test_rspec.py
tests/test_runners/test_cts.py
tests/test_runners/test_playwright.py

@ono-max ono-max requested a review from Konboi January 21, 2025 07:12
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)
launchable/commands/subset.py (2)

636-637: Add function documentation.

Add a docstring to explain the function's purpose, parameters, and return value.

Apply this diff to add documentation:

 def subset_request(client: LaunchableClient, timeout: Tuple[int, int], payload: Dict[str, Any]):
+    """Send a subset request to the Launchable API.
+
+    Args:
+        client: LaunchableClient instance for making API requests
+        timeout: Tuple of (connect timeout, read timeout) in seconds
+        payload: Request payload containing test paths and configuration
+
+    Returns:
+        Response from the subset API endpoint
+
+    Raises:
+        requests.exceptions.RequestException: If the API request fails
+    """
     return client.request("post", "subset", timeout=timeout, payload=payload, compress=True)

519-526: Consider implementing a request management system.

The current non-blocking implementation could benefit from a more robust architecture:

  1. Request Queue Management:

    • Implement a queue system to manage multiple concurrent requests
    • Add rate limiting to prevent resource exhaustion
    • Provide a way to list and cancel pending requests
  2. Status Monitoring:

    • Add a new command to check the status of non-blocking requests
    • Implement a simple status API endpoint
    • Store request metadata in a structured format

Would you like me to propose a detailed design for these improvements?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 21a56d4 and a159014.

📒 Files selected for processing (1)
  • launchable/commands/subset.py (6 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (14)
  • GitHub Check: build (windows-latest, 3.12)
  • GitHub Check: build (windows-latest, 3.11)
  • GitHub Check: build (windows-latest, 3.10)
  • GitHub Check: build (windows-latest, 3.9)
  • GitHub Check: build (windows-latest, 3.8)
  • GitHub Check: build (windows-latest, 3.7)
  • GitHub Check: build (windows-latest, 3.6)
  • GitHub Check: build (ubuntu-20.04, 3.12)
  • GitHub Check: build (ubuntu-20.04, 3.11)
  • GitHub Check: build (ubuntu-20.04, 3.10)
  • GitHub Check: build (ubuntu-20.04, 3.9)
  • GitHub Check: build (ubuntu-20.04, 3.8)
  • GitHub Check: build (ubuntu-20.04, 3.7)
  • GitHub Check: build (ubuntu-20.04, 3.6)
🔇 Additional comments (3)
launchable/commands/subset.py (3)

135-141: LGTM! Option definition follows best practices.

The --non-blocking option is correctly defined as a hidden flag, following the reviewer's suggestion to mark it as experimental.


235-247: LGTM! Validation logic is thorough and consistent.

The validation ensures that --non-blocking is used only with --observation mode, with proper error handling that follows the codebase's patterns.


519-526: ⚠️ Potential issue

Add robust process management and error handling.

The current implementation of non-blocking mode needs improvement in several areas:

  1. No error handling for process creation/execution
  2. No cleanup of zombie processes
  3. No way to track the subset request status

Apply this diff to add proper error handling and process management:

     if is_non_blocking:
+        process = None
+        try:
             # Create a new process for requesting a subset.
-            process = Process(target=subset_request, args=(client, timeout, payload))
-            process.start()
+            process = Process(target=subset_request, args=(client, timeout, payload), daemon=True)
+            process.start()
+            # Store process information for tracking
+            process_info = {
+                "pid": process.pid,
+                "session_id": session_id,
+                "timestamp": datetime.now().isoformat()
+            }
+            tracking_file = os.path.join(app.get_metadata_dir(), f"subset_process_{session_id}.json")
+            with open(tracking_file, "w") as f:
+                json.dump(process_info, f)
             click.echo("The subset was requested in non-blocking mode.")
+            click.echo(f"Process ID: {process.pid}")
+            click.echo(f"Track status: {tracking_file}")
             self.output_handler(self.test_paths, [])
             return
+        except Exception as e:
+            if process and process.is_alive():
+                process.terminate()
+            msg = f"Failed to start non-blocking subset request: {str(e)}"
+            click.echo(click.style(msg, fg="red"), err=True)
+            tracking_client.send_error_event(
+                event_name=Tracking.ErrorEvent.INTERNAL_CLI_ERROR,
+                stack_trace=str(e),
+            )
+            sys.exit(1)

Likely invalid or redundant comment.

# Create a new process for requesting a subset.
process = Process(target=subset_request, args=(client, timeout, payload))
process.start()
click.echo("The subset was requested in non-blocking mode.")
Copy link
Contributor

Choose a reason for hiding this comment

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

As far as I remember, click.echo outputs as stdout. It means this message ("The subset was requested in non-blocking mode.") will be included as subset out. So you should print this message as stderr. ( I know it's a little tricky 😅)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, thank you for telling me that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

@Konboi Konboi left a comment

Choose a reason for hiding this comment

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

Could you run test with --non-blocking option once as test before merging this PR?

https://github.com/launchableinc/cli/blob/main/.github/workflows/python-package.yml#L102

or add example to this repo https://github.com/launchableinc/examples

@ono-max
Copy link
Contributor Author

ono-max commented Jan 21, 2025

@Konboi

I confirmed it worked in #964. While testing it, I noticed that I have to remove the validation: 296aaf0.
It's because a user might configure observation mode in launchable record session command. So, it's a little complex to validate the logic.

@ono-max ono-max requested a review from Konboi January 21, 2025 22:17
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)
launchable/commands/subset.py (1)

Line range hint 509-627: Add retry mechanism for subset requests.

Consider adding a retry mechanism for subset requests to handle transient network issues, especially important in non-blocking mode where the user won't see immediate failures.

I can help implement a retry mechanism with exponential backoff if you'd like. Would you like me to open an issue for this enhancement?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a159014 and 586f43d.

📒 Files selected for processing (1)
  • launchable/commands/subset.py (6 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (14)
  • GitHub Check: build (windows-latest, 3.12)
  • GitHub Check: build (windows-latest, 3.11)
  • GitHub Check: build (windows-latest, 3.10)
  • GitHub Check: build (windows-latest, 3.9)
  • GitHub Check: build (windows-latest, 3.8)
  • GitHub Check: build (windows-latest, 3.7)
  • GitHub Check: build (windows-latest, 3.6)
  • GitHub Check: build (ubuntu-20.04, 3.12)
  • GitHub Check: build (ubuntu-20.04, 3.11)
  • GitHub Check: build (ubuntu-20.04, 3.10)
  • GitHub Check: build (ubuntu-20.04, 3.9)
  • GitHub Check: build (ubuntu-20.04, 3.8)
  • GitHub Check: build (ubuntu-20.04, 3.7)
  • GitHub Check: build (ubuntu-20.04, 3.6)
🔇 Additional comments (4)
launchable/commands/subset.py (4)

6-6: LGTM!

The Process import from multiprocessing is correctly added for implementing the non-blocking mode.


135-141: LGTM!

The --non-blocking option is well-defined with:

  • Clear help text explaining its purpose
  • Hidden flag as suggested in past reviews
  • Proper type as a boolean flag

626-627: LGTM!

The subset_request function is well-defined with:

  • Clear type hints
  • Proper parameter types
  • Single responsibility

509-516: ⚠️ Potential issue

Improve process error handling and cleanup.

The current implementation of non-blocking mode lacks:

  1. Error handling for process creation/start failures
  2. Cleanup of zombie processes
  3. Process status tracking

Apply this diff to add error handling and process management:

     if is_non_blocking:
+        try:
             # Create a new process for requesting a subset.
-            process = Process(target=subset_request, args=(client, timeout, payload))
-            process.start()
+            process = Process(target=subset_request, args=(client, timeout, payload), daemon=True)
+            process.start()
+            # Store the process ID for potential future use
+            process_file = os.path.join(app.get_metadata_dir(), f"subset_process_{session_id}.pid")
+            with open(process_file, "w") as f:
+                f.write(str(process.pid))
+        except Exception as e:
+            msg = f"Failed to start non-blocking subset request: {str(e)}"
+            click.echo(click.style(msg, fg="red"), err=True)
+            tracking_client.send_error_event(
+                event_name=Tracking.ErrorEvent.INTERNAL_CLI_ERROR,
+                stack_trace=str(e),
+            )
+            sys.exit(1)
         click.echo("The subset was requested in non-blocking mode.", err=True)
         self.output_handler(self.test_paths, [])
         return

Likely invalid or redundant comment.

Comment on lines 221 to 224
if is_non_blocking:
click.echo("Observation mode is automatically enabled in non-blocking mode.", err=True)
is_observation = True

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

Add validation to ensure non-blocking mode is used only with observation mode.

The current implementation automatically enables observation mode when non-blocking is used, but it should validate that non-blocking mode cannot be used without observation mode.

Apply this diff to add the validation:

     if is_non_blocking:
+        if not is_observation:
+            msg = "Non-blocking mode can only be used with observation mode"
+            click.echo(click.style(msg, fg="red"), err=True)
+            tracking_client.send_error_event(
+                event_name=Tracking.ErrorEvent.INTERNAL_CLI_ERROR,
+                stack_trace=msg,
+            )
+            sys.exit(1)
         click.echo("Observation mode is automatically enabled in non-blocking mode.", err=True)
         is_observation = True
📝 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 is_non_blocking:
click.echo("Observation mode is automatically enabled in non-blocking mode.", err=True)
is_observation = True
if is_non_blocking:
if not is_observation:
msg = "Non-blocking mode can only be used with observation mode"
click.echo(click.style(msg, fg="red"), err=True)
tracking_client.send_error_event(
event_name=Tracking.ErrorEvent.INTERNAL_CLI_ERROR,
stack_trace=msg,
)
sys.exit(1)
click.echo("Observation mode is automatically enabled in non-blocking mode.", err=True)
is_observation = True

@Konboi
Copy link
Contributor

Konboi commented Jan 22, 2025

It's because a user might configure observation mode in launchable record session command

Nice catch!

But I think this validation (296aaf0) is really helpful not only user but also Launchable side...
So how about adding the field like observation: true (or false) to the .launchablefile

If we did, we can validate it correctly, right?

WDYT??

@sonarqubecloud
Copy link

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 (1)
launchable/commands/subset.py (1)

303-330: Simplify nested if statements.

The validation logic is correct, but the code structure can be simplified.

-    if is_non_blocking:
-        if (not is_observation) and session_id:
+    if is_non_blocking and (not is_observation) and session_id:
🧰 Tools
🪛 Ruff (0.8.2)

303-304: Use a single if statement instead of nested if statements

(SIM102)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 586f43d and 5fc6322.

📒 Files selected for processing (1)
  • launchable/commands/subset.py (6 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
launchable/commands/subset.py

303-304: Use a single if statement instead of nested if statements

(SIM102)

⏰ Context from checks skipped due to timeout of 90000ms (14)
  • GitHub Check: build (windows-latest, 3.12)
  • GitHub Check: build (windows-latest, 3.11)
  • GitHub Check: build (windows-latest, 3.10)
  • GitHub Check: build (windows-latest, 3.9)
  • GitHub Check: build (windows-latest, 3.8)
  • GitHub Check: build (windows-latest, 3.7)
  • GitHub Check: build (windows-latest, 3.6)
  • GitHub Check: build (ubuntu-20.04, 3.12)
  • GitHub Check: build (ubuntu-20.04, 3.11)
  • GitHub Check: build (ubuntu-20.04, 3.10)
  • GitHub Check: build (ubuntu-20.04, 3.9)
  • GitHub Check: build (ubuntu-20.04, 3.8)
  • GitHub Check: build (ubuntu-20.04, 3.7)
  • GitHub Check: build (ubuntu-20.04, 3.6)
🔇 Additional comments (3)
launchable/commands/subset.py (3)

135-141: LGTM: CLI option is well-defined.

The --non-blocking option is properly implemented as a hidden option with clear help text.


650-651: LGTM: Helper function is well-defined.

The subset_request function is properly implemented with correct type hints and encapsulates the request logic effectively.


533-540: 🛠️ Refactor suggestion

Add process error handling and cleanup.

The current implementation lacks proper process management:

  1. No error handling for process creation/start failures
  2. No cleanup of zombie processes
  3. No way to track the status of the subset request
     if is_non_blocking:
+        try:
             # Create a new process for requesting a subset.
-            process = Process(target=subset_request, args=(client, timeout, payload))
-            process.start()
+            process = Process(target=subset_request, args=(client, timeout, payload), daemon=True)
+            process.start()
+            # Store the process ID for potential future use
+            with open(os.path.join(app.get_metadata_dir(), f"subset_process_{session_id}.pid"), "w") as f:
+                f.write(str(process.pid))
+        except Exception as e:
+            msg = f"Failed to start non-blocking subset request: {str(e)}"
+            click.echo(click.style(msg, fg="red"), err=True)
+            tracking_client.send_error_event(
+                event_name=Tracking.ErrorEvent.INTERNAL_CLI_ERROR,
+                stack_trace=str(e),
+            )
+            sys.exit(1)
         click.echo("The subset was requested in non-blocking mode.", err=True)
         self.output_handler(self.test_paths, [])
         return

Likely invalid or redundant comment.

@ono-max
Copy link
Contributor Author

ono-max commented Jan 22, 2025

@Konboi

I archived the solution by getting a test session in HTTP request: 5fc6322

I think that it would be simpler. What do you think?

I confirmed it worked in the following PRs.

Failure: #969
Success: #970

Copy link
Contributor

@Konboi Konboi left a comment

Choose a reason for hiding this comment

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

LGTM


Great work!

@ono-max ono-max merged commit 17189db into main Jan 23, 2025
17 checks passed
@ono-max ono-max deleted the non-blocking branch January 23, 2025 03:04
@github-actions github-actions bot mentioned this pull request Jan 23, 2025
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.

3 participants