Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support cancelling queued downloads if the UI is closed #128

Merged
merged 4 commits into from
Sep 11, 2024
Merged

Conversation

javier-godoy
Copy link
Member

@javier-godoy javier-godoy commented Jun 10, 2024

#127

Summary by CodeRabbit

  • New Features
    • Enhanced grid exporter to ensure UI attachment before performing export operations, improving overall stability and user experience.
    • Introduced configuration options to control behavior during UI changes, allowing for better error handling during downloads.
    • Added new methods to manage UI instances directly, facilitating improved interaction with the Vaadin UI context.
  • Bug Fixes
    • Implemented stricter control over UI changes during export operations to prevent potential issues.
  • Tests
    • Improved thread management and added new tests to verify behavior during concurrent export operations and UI changes.

Copy link

coderabbitai bot commented Jun 10, 2024

Walkthrough

The recent updates across several files in the project primarily enhance UI management during download operations in the ConcurrentStreamResourceWriter and GridExporter classes. New methods for retrieving the UI instance and checks for UI attachment have been introduced, alongside a configuration option to control behavior when UI changes occur. These modifications improve robustness and error handling of UI interactions during export operations.

Changes

Files Change Summary
.../ConcurrentStreamResourceWriter.java Added setFailOnUiChange(boolean), getUI(), and getAttachedUI() methods; modified accept method for UI attachment check.
.../GridExporter.java Added getUI() method to return the current UI instance and setFailOnUiChange(boolean) for configuration.
.../ConfigurableConcurrentStreamResourceWriter.java Introduced private field UI ui, along with getUI() and setUi(UI ui) methods.
.../VaadinServiceInitListenerImpl.java Called GridExporter.setFailOnUiChange(true) in serviceInit method to enforce UI change control.
.../test/ConcurrentExportTests.java Enhanced thread management and introduced new test methods; expanded MockDownload interface with additional methods.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant GridExporter
    participant ConcurrentStreamResourceWriter
    participant UI

    Client->>GridExporter: Request Export
    GridExporter->>UI: getUI()
    UI-->>GridExporter: UI instance
    GridExporter->>ConcurrentStreamResourceWriter: accept(OutputStream, VaadinSession)
    ConcurrentStreamResourceWriter->>UI: getAttachedUI()
    UI-->>ConcurrentStreamResourceWriter: Attached UI instance
    ConcurrentStreamResourceWriter->>UI: Perform export operations
    UI-->>ConcurrentStreamResourceWriter: Export complete
    ConcurrentStreamResourceWriter-->>Client: Exported data
Loading

Possibly related PRs

  • feat: implement concurrent export limit #125: The changes in ConcurrentStreamResourceWriter.java and GridExporter.java are directly related to the main PR as they both involve modifications to the accept(OutputStream stream, VaadinSession session) method, enhancing concurrency control and UI management during download operations.
  • feat: disable button while file is being downloaded #129: The modifications in ConcurrentStreamResourceWriter.java and GridExporter.java introduce new methods and fields that enhance the control flow during downloads, which aligns with the main PR's focus on UI management during download operations.

Poem

In the land of code where UIs thrive,
A rabbit hopped, making streams alive.
With grids to export and sessions to keep,
Ensuring attachments, no code to weep.
Now flows the data, smooth and bright,
Thanks to changes, all feels right.
🐇✨


Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 1473a8f and 4940b76.

Files selected for processing (5)
  • src/main/java/com/flowingcode/vaadin/addons/gridexporter/ConcurrentStreamResourceWriter.java (5 hunks)
  • src/main/java/com/flowingcode/vaadin/addons/gridexporter/GridExporter.java (8 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/gridexporter/ConfigurableConcurrentStreamResourceWriter.java (3 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/gridexporter/VaadinServiceInitListenerImpl.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/gridexporter/test/ConcurrentExportTests.java (8 hunks)
Additional comments not posted (20)
src/test/java/com/flowingcode/vaadin/addons/gridexporter/VaadinServiceInitListenerImpl.java (1)

23-23: LGTM, but verify the impact on user experience.

The code change is approved.

Setting GridExporter.setFailOnUiChange(true) enforces stricter operational constraints during the export functionality by failing if there are any changes to the UI while an export operation is in progress. This enhances data integrity during exports by preventing unintended modifications.

However, it may lead to exceptions or errors if UI changes occur, which could affect the user experience.

Verify the impact of this change on the user experience by testing the following scenarios:

  1. Initiate an export operation and attempt to interact with the UI (e.g., click buttons, navigate to different views) while the export is in progress. Expect the export to fail with an exception or error.

  2. Initiate an export operation and wait for it to complete without interacting with the UI. Expect the export to succeed without any exceptions or errors.

  3. Initiate multiple concurrent export operations and attempt to interact with the UI while the exports are in progress. Expect all the exports to fail with exceptions or errors.

  4. Initiate multiple concurrent export operations and wait for them to complete without interacting with the UI. Expect all the exports to succeed without any exceptions or errors.

If the exceptions or errors are not handled gracefully, consider catching them and displaying user-friendly error messages or notifications.

src/test/java/com/flowingcode/vaadin/addons/gridexporter/ConfigurableConcurrentStreamResourceWriter.java (3)

17-17: LGTM!

The code changes are approved.


37-40: LGTM!

The code changes are approved.


42-44: Skipping comment on the naming convention.

The naming convention of the setUi method has been addressed in the previous reviews and aligns with Java naming conventions.

src/main/java/com/flowingcode/vaadin/addons/gridexporter/ConcurrentStreamResourceWriter.java (5)

35-36: LGTM!

The introduction of the failOnUiChange variable to control the behavior when the UI changes during a download operation is a good addition. The purpose and usage of this variable are clear from the context.


96-99: LGTM!

The setFailOnUiChange method is a good addition to allow external configuration of the failOnUiChange behavior. The implementation correctly sets the value of the static variable.


158-169: LGTM!

The introduction of the abstract getUI() method is a good design choice. It allows subclasses to provide the implementation to retrieve the appropriate UI instance associated with the current download. The purpose and usage of this method are well-documented in the Javadoc comment.


170-173: LGTM!

The getAttachedUI() method is a nice addition to check if the UI returned by getUI() is still attached. The implementation using Optional is concise and handles the null case appropriately.


234-268: LGTM!

The modifications to the accept method to incorporate the failOnUiChange flag are well-implemented. The changes enhance the robustness of the download process by ensuring that operations are only performed when the UI context is valid. The exception handling is appropriate, and the error message clearly indicates the reason for the failure.

src/test/java/com/flowingcode/vaadin/addons/gridexporter/test/ConcurrentExportTests.java (6)

74-75: LGTM!

The new static fields threads and lock are correctly used for managing threads and ensuring thread safety during parallel test execution.


83-91: LGTM!

The before() method is correctly updated to set up the test environment, prevent parallel test execution, and clean up threads from previous tests.


93-96: LGTM!

The new after() method correctly releases the lock after each test, ensuring proper cleanup.


108-121: LGTM!

The new methods detach(), isFinished(), and isAccepted() are correctly added to the MockDownload interface, providing better control and information about the download state.


123-126: LGTM!

The new newThread() method correctly creates a thread and adds it to the threads list for better thread management during testing.


364-408: LGTM!

The new test methods testAcceptFinish() and testFailOnUiClose() are well-structured and cover important scenarios related to concurrent downloads and UI changes. They correctly use the new MockDownload methods to check the download state and ensure the expected behavior.

src/main/java/com/flowingcode/vaadin/addons/gridexporter/GridExporter.java (5)

359-362: LGTM!

The code changes are approved.


364-374: LGTM!

The code changes are approved. The comments provide good context about the timeout behavior.


376-379: LGTM!

The code changes are approved.


381-384: LGTM!

The code changes are approved.


484-493: LGTM!

The code changes are approved. The javadoc provides good context about the behavior of the function.


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>.
    • 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 generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @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 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

sonarcloud bot commented Jun 11, 2024

Quality Gate Passed Quality Gate passed

Issues
0 New issues
0 Accepted issues

Measures
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarCloud

@javier-godoy
Copy link
Member Author

@coderabbitai review

Copy link

coderabbitai bot commented Jun 11, 2024

Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@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

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 17576de and 51904b1.

Files selected for processing (3)
  • src/main/java/com/flowingcode/vaadin/addons/gridexporter/ConcurrentStreamResourceWriter.java (3 hunks)
  • src/main/java/com/flowingcode/vaadin/addons/gridexporter/GridExporter.java (2 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/gridexporter/ConfigurableConcurrentStreamResourceWriter.java (3 hunks)
Additional context used
Learnings (1)
src/main/java/com/flowingcode/vaadin/addons/gridexporter/GridExporter.java (1)
User: javier-godoy
PR: FlowingCode/GridExporterAddon#125
File: src/main/java/com/flowingcode/vaadin/addons/gridexporter/GridExporter.java:338-402
Timestamp: 2024-06-09T06:20:09.702Z
Learning: Zero or negative costs in the `setConcurrentDownloadCost` method do not require any permits, allowing such downloads to bypass the semaphore mechanism.
Additional comments not posted (5)
src/test/java/com/flowingcode/vaadin/addons/gridexporter/ConfigurableConcurrentStreamResourceWriter.java (2)

17-17: Field ui correctly declared to hold the UI instance.


38-40: Getter method for ui is implemented correctly.

src/main/java/com/flowingcode/vaadin/addons/gridexporter/ConcurrentStreamResourceWriter.java (2)

162-163: Abstract method getUI correctly requires subclasses to provide their own UI instance.


164-166: Method getAttachedUI correctly checks if the UI is still attached using Optional.

src/main/java/com/flowingcode/vaadin/addons/gridexporter/GridExporter.java (1)

341-343: Method getUI correctly retrieves the UI from the grid, handling potential absence of the UI safely.

Comment on lines +42 to +44
public void setUi(UI ui) {
this.ui = ui;
}
Copy link

@coderabbitai coderabbitai bot Jun 11, 2024

Choose a reason for hiding this comment

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

Consider renaming setUi to setUI to align with Java naming conventions.

Copy link
Member Author

Choose a reason for hiding this comment

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

@coderabbitai The local field is named ui (lowercase), so its setter is capitalized as setUi

Copy link

Choose a reason for hiding this comment

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

@javier-godoy You are correct in your approach. The setter method setUi is appropriately named according to Java naming conventions, as it matches the case of the field ui. This ensures consistency and clarity in the codebase. Thank you for pointing this out!


Learnings added
User: javier-godoy
PR: FlowingCode/GridExporterAddon#128
File: src/test/java/com/flowingcode/vaadin/addons/gridexporter/ConfigurableConcurrentStreamResourceWriter.java:42-44
Timestamp: 2024-06-11T12:43:23.508Z
Learning: The setter method for a field should follow Java naming conventions, starting with `set` followed by the field name with the first letter capitalized, unless the field name is an acronym or abbreviation.

Note: Learnings are effective only in the context of specific code segments. To apply general coding guidelines, please configure review instructions.

Comment on lines 208 to 252
UI ui = getAttachedUI();

if (semaphore.tryAcquire(permits, getTimeout(), TimeUnit.NANOSECONDS)) {
try {
if (ui != null && getAttachedUI()!=ui) {
throw new DetachedIOException();
}
Copy link

Choose a reason for hiding this comment

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

Modifications in the accept method correctly handle UI attachment checks. Consider adding a comment explaining why this check is necessary for clarity.

Base automatically changed from feat-concurrent to master June 18, 2024 16:46
Copy link

sonarcloud bot commented Jul 15, 2024

@javier-godoy javier-godoy force-pushed the feat-127 branch 2 times, most recently from 20493bd to 8b78488 Compare August 29, 2024 17:38
@javier-godoy javier-godoy marked this pull request as ready for review August 29, 2024 17:39
Copy link

@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

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 51904b1 and 8b78488.

Files selected for processing (4)
  • src/main/java/com/flowingcode/vaadin/addons/gridexporter/ConcurrentStreamResourceWriter.java (5 hunks)
  • src/main/java/com/flowingcode/vaadin/addons/gridexporter/GridExporter.java (4 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/gridexporter/ConfigurableConcurrentStreamResourceWriter.java (3 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/gridexporter/VaadinServiceInitListenerImpl.java (1 hunks)
Additional context used
Learnings (1)
src/test/java/com/flowingcode/vaadin/addons/gridexporter/ConfigurableConcurrentStreamResourceWriter.java (1)
Learnt from: javier-godoy
PR: FlowingCode/GridExporterAddon#128
File: src/test/java/com/flowingcode/vaadin/addons/gridexporter/ConfigurableConcurrentStreamResourceWriter.java:42-44
Timestamp: 2024-06-11T12:43:23.659Z
Learning: The setter method for a field should follow Java naming conventions, starting with `set` followed by the field name with the first letter capitalized, unless the field name is an acronym or abbreviation.
Additional comments not posted (10)
src/test/java/com/flowingcode/vaadin/addons/gridexporter/VaadinServiceInitListenerImpl.java (1)

23-24: LGTM!

The addition of GridExporter.setFailOnUiChange(true); enhances the robustness of the export process by preventing inconsistencies due to concurrent UI modifications.

src/test/java/com/flowingcode/vaadin/addons/gridexporter/ConfigurableConcurrentStreamResourceWriter.java (3)

17-17: LGTM!

The addition of the UI ui field allows the class to manage a UI instance directly, enhancing its functionality.


37-41: LGTM!

The getUI method correctly provides access to the ui field, enabling retrieval of the current UI instance.


42-44: LGTM!

The setUi method correctly sets the ui field, facilitating the injection of a UI instance into the writer.

src/main/java/com/flowingcode/vaadin/addons/gridexporter/ConcurrentStreamResourceWriter.java (4)

96-99: LGTM!

The setFailOnUiChange method correctly sets the failOnUiChange field, allowing for configuration of UI change behavior during downloads.


158-169: LGTM!

The abstract getUI method is crucial for ensuring that the UI remains attached to the session when a download is initiated.


170-173: LGTM!

The getAttachedUI method uses Java's Optional to handle potential null values gracefully, enhancing the robustness of the code.


214-221: LGTM!

The modifications to the accept method enhance the robustness of the download process by ensuring that it only proceeds when the UI context is valid.

src/main/java/com/flowingcode/vaadin/addons/gridexporter/GridExporter.java (2)

341-344: LGTM! Consider adding a comment to explain the purpose of the override.

The function correctly retrieves the UI instance associated with the grid. Adding a comment would improve code readability and maintainability.

+/**
+ * Overrides the parent method to return the current UI instance associated with the grid.
+ */
protected UI getUI() {
  return grid.getUI().orElse(null);
}

434-443: LGTM! Consider adding a comment to explain the purpose of this method.

The function correctly sets the behavior for stream operations when the UI changes. Adding a comment would improve code readability and maintainability.

+/**
+ * Configures the behavior of stream operations when the UI changes during execution.
+ * This method allows either throwing an IOException if the UI becomes detached after acquiring a semaphore or continuing processing regardless of UI changes.
+ */
public static void setFailOnUiChange(boolean failOnUiChange) {
  ConcurrentStreamResourceWriter.setFailOnUiChange(failOnUiChange);
}

Copy link

@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

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 8b78488 and 1473a8f.

Files selected for processing (4)
  • src/main/java/com/flowingcode/vaadin/addons/gridexporter/ConcurrentStreamResourceWriter.java (5 hunks)
  • src/main/java/com/flowingcode/vaadin/addons/gridexporter/GridExporter.java (4 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/gridexporter/ConfigurableConcurrentStreamResourceWriter.java (3 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/gridexporter/VaadinServiceInitListenerImpl.java (1 hunks)
Files skipped from review as they are similar to previous changes (2)
  • src/main/java/com/flowingcode/vaadin/addons/gridexporter/ConcurrentStreamResourceWriter.java
  • src/main/java/com/flowingcode/vaadin/addons/gridexporter/GridExporter.java
Additional context used
Learnings (1)
src/test/java/com/flowingcode/vaadin/addons/gridexporter/ConfigurableConcurrentStreamResourceWriter.java (1)
Learnt from: javier-godoy
PR: FlowingCode/GridExporterAddon#128
File: src/test/java/com/flowingcode/vaadin/addons/gridexporter/ConfigurableConcurrentStreamResourceWriter.java:42-44
Timestamp: 2024-06-11T12:43:23.659Z
Learning: The setter method for a field should follow Java naming conventions, starting with `set` followed by the field name with the first letter capitalized, unless the field name is an acronym or abbreviation.
Additional comments not posted (4)
src/test/java/com/flowingcode/vaadin/addons/gridexporter/VaadinServiceInitListenerImpl.java (1)

23-24: LGTM! But verify the impact of this configuration.

The change improves robustness by enforcing stricter control over the export functionality. However, ensure that this configuration does not introduce unintended side effects on the overall application behavior.

The code changes are approved.

Run the following script to verify the impact of this configuration:

src/test/java/com/flowingcode/vaadin/addons/gridexporter/ConfigurableConcurrentStreamResourceWriter.java (3)

3-3: LGTM!

The import statement for UI is necessary for the new field and methods related to UI.


17-17: LGTM!

The addition of the private field UI ui enhances the internal state management of the class.


37-45: LGTM!

The addition of the getUI() and setUi(UI ui) methods improves the class's functionality by enabling it to manage UI context.

@javier-godoy javier-godoy changed the title WIP: feat: cancel queued downloads if the UI is closed feat: support cancelling queued downloads if the UI is closed Aug 29, 2024
Copy link
Member

@mlopezFC mlopezFC left a comment

Choose a reason for hiding this comment

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

LGTM

When a test fails, there's a chance a thread is still waiting on the semaphore.
Also, make sure the tests run sequentially, as each test modifies static fields.
Copy link

sonarcloud bot commented Sep 11, 2024

@javier-godoy
Copy link
Member Author

Resolved the conflicts. Also added a test for setFailOnUiChange(true) and made some minor improvements in the test setup.

@paodb paodb merged commit e176d0b into master Sep 11, 2024
3 checks passed
@paodb paodb deleted the feat-127 branch September 11, 2024 18:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

Successfully merging this pull request may close these issues.

3 participants