Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

imbajin
Copy link

@imbajin imbajin commented Jun 12, 2025

The test testBalancePartitionLeader was prone to a ConcurrentModificationException because the TaskScheduleService could still be running background tasks when the cleanup method getStoreNodeService().getStoreInfoMeta().removeAll() was called. These background tasks might be iterating over data that removeAll() modifies, leading to the exception.

This commit addresses the issue by:

  1. Introducing an @After method (tearDown) in TaskScheduleServiceTest.java.
  2. In the tearDown method, the TaskScheduleService instance (this.service) is now explicitly shut down using this.service.shutDown() before any cleanup operations are performed.
  3. The call to getStoreNodeService().getStoreInfoMeta().removeAll() has been moved from the testBalancePartitionLeader method into the new tearDown method to ensure it runs after the service shutdown.

This change ensures that all background activity is stopped before data cleanup, preventing potential concurrent modifications.

The test `testBalancePartitionLeader` was prone to a
ConcurrentModificationException because the `TaskScheduleService`
could still be running background tasks when the cleanup method
`getStoreNodeService().getStoreInfoMeta().removeAll()` was called.
These background tasks might be iterating over data that `removeAll()`
modifies, leading to the exception.

This commit addresses the issue by:
1. Introducing an `@After` method (`tearDown`) in `TaskScheduleServiceTest.java`.
2. In the `tearDown` method, the `TaskScheduleService` instance (`this.service`)
   is now explicitly shut down using `this.service.shutDown()` before
   any cleanup operations are performed.
3. The call to `getStoreNodeService().getStoreInfoMeta().removeAll()` has been
   moved from the `testBalancePartitionLeader` method into the new
   `tearDown` method to ensure it runs after the service shutdown.

This change ensures that all background activity is stopped before
data cleanup, preventing potential concurrent modifications.
@Copilot Copilot AI review requested due to automatic review settings June 12, 2025 10:17
@dosubot dosubot bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Jun 12, 2025
Copy link

@codecov-ai-reviewer review

Copy link

codecov-ai bot commented Jun 12, 2025

On it! We are reviewing the PR and will provide feedback shortly.

@dosubot dosubot bot added the bug Something isn't working label Jun 12, 2025
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Adds a teardown step to stop background tasks before cleaning up store metadata, preventing ConcurrentModificationException in testBalancePartitionLeader.

  • Introduces an @After-annotated tearDown to shut down TaskScheduleService and call removeAll()
  • Moves the removeAll() call out of testBalancePartitionLeader
  • Adds the necessary JUnit @After import
Comments suppressed due to low confidence (1)

hugegraph-pd/hg-pd-test/src/main/java/org/apache/hugegraph/pd/core/TaskScheduleServiceTest.java:50

  • The TODO testStoreOffline method is missing an @test annotation and won't execute; consider adding @test or marking it @ignore to clarify its status.
public void testStoreOffline() {

@After
public void tearDown() {
if (this.service != null) {
this.service.shutDown();
Copy link

Copilot AI Jun 12, 2025

Choose a reason for hiding this comment

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

shutDown() initiates shutdown but returns immediately; consider adding an awaitTermination(timeout) call after shutDown() to ensure all background tasks have fully stopped before cleanup.

Suggested change
this.service.shutDown();
this.service.shutDown();
try {
this.service.awaitTermination(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Failed to await termination of TaskScheduleService", e);
}

Copilot uses AI. Check for mistakes.

Comment on lines +44 to +46
this.service.shutDown();
}
getStoreNodeService().getStoreInfoMeta().removeAll();
Copy link

Copilot AI Jun 12, 2025

Choose a reason for hiding this comment

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

Wrap the shutdown and cleanup logic in a try/finally block so that removeAll() always runs even if shutDown() throws an exception.

Suggested change
this.service.shutDown();
}
getStoreNodeService().getStoreInfoMeta().removeAll();
try {
this.service.shutDown();
} finally {
getStoreNodeService().getStoreInfoMeta().removeAll();
}
}

Copilot uses AI. Check for mistakes.

Copy link

codecov-ai bot commented Jun 12, 2025

PR Description

This pull request aims to improve the reliability and maintainability of the TaskScheduleServiceTest by introducing a centralized tearDown method for cleaning up resources after each test execution. This ensures consistent test environments and prevents potential state leakage between tests.

Click to see more

Key Technical Changes

The key technical change is the addition of the @After annotated tearDown() method. This method is responsible for shutting down the TaskScheduleService and removing all store info metadata. The cleanup line getStoreNodeService().getStoreInfoMeta().removeAll(); was removed from the testBalancePartitionLeader() method and moved to the tearDown() method.

Architecture Decisions

The architectural decision is to adopt a centralized cleanup strategy using JUnit's @After annotation. This promotes code reuse, reduces redundancy, and ensures that cleanup operations are consistently executed regardless of test outcome.

Dependencies and Interactions

This change primarily affects the TaskScheduleServiceTest class itself. It depends on the getTaskService() and getStoreNodeService() methods, which are assumed to be provided by a base class or dependency injection. It interacts with the TaskScheduleService to shut it down and with the store info metadata to remove all entries.

Risk Considerations

The primary risk is that the tearDown() method might not completely clean up all resources, potentially leading to test interference. It's crucial to ensure that the tearDown() method effectively resets the system state to a clean starting point. Also, potential exceptions during cleanup in tearDown() should be handled gracefully to avoid masking actual test failures.

Notable Implementation Details

The tearDown() method shuts down the TaskScheduleService and removes all store info metadata. Reviewers should pay close attention to the completeness of the cleanup operations and ensure that all relevant resources are properly released or reset. Consider adding null checks and exception handling to the tearDown() method for robustness.

Comment on lines +41 to +47
@After
public void tearDown() {
if (this.service != null) {
this.service.shutDown();
}
getStoreNodeService().getStoreInfoMeta().removeAll();
}
Copy link

Choose a reason for hiding this comment

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

Good improvement: Adding a centralized tearDown method is excellent for test hygiene. This ensures consistent cleanup after each test method and prevents state leakage between tests.

Comment on lines +44 to +46
this.service.shutDown();
}
getStoreNodeService().getStoreInfoMeta().removeAll();
Copy link

Choose a reason for hiding this comment

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

Consider adding null check for defensive programming: While the service null check is good, consider also checking if getStoreNodeService() returns null before calling methods on it to prevent potential NullPointerException.

Suggested change
this.service.shutDown();
}
getStoreNodeService().getStoreInfoMeta().removeAll();
@After
public void tearDown() {
if (this.service != null) {
this.service.shutDown();
}
if (getStoreNodeService() != null && getStoreNodeService().getStoreInfoMeta() != null) {
getStoreNodeService().getStoreInfoMeta().removeAll();
}
}

Comment on lines 83 to 84
getPdConfig().getPartition().setShardCount(1);
getStoreNodeService().getStoreInfoMeta().removeAll();
}
Copy link

Choose a reason for hiding this comment

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

Excellent refactoring: Moving the cleanup code from the individual test method to the centralized tearDown method improves maintainability and ensures consistent cleanup across all tests. This follows the DRY principle and reduces code duplication.

Comment on lines +41 to +47
@After
public void tearDown() {
if (this.service != null) {
this.service.shutDown();
}
getStoreNodeService().getStoreInfoMeta().removeAll();
}
Copy link

Choose a reason for hiding this comment

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

Consider exception handling: The tearDown method should handle potential exceptions during cleanup to prevent masking test failures. Consider wrapping cleanup operations in try-catch blocks and logging any cleanup failures.

Suggested change
@After
public void tearDown() {
if (this.service != null) {
this.service.shutDown();
}
getStoreNodeService().getStoreInfoMeta().removeAll();
}
@After
public void tearDown() {
try {
if (this.service != null) {
this.service.shutDown();
}
} catch (Exception e) {
// Log cleanup failure but don't fail the test
System.err.println("Failed to shutdown service: " + e.getMessage());
}
try {
if (getStoreNodeService() != null && getStoreNodeService().getStoreInfoMeta() != null) {
getStoreNodeService().getStoreInfoMeta().removeAll();
}
} catch (Exception e) {
// Log cleanup failure but don't fail the test
System.err.println("Failed to clear store info meta: " + e.getMessage());
}
}

Comment on lines +41 to +47
@After
public void tearDown() {
if (this.service != null) {
this.service.shutDown();
}
getStoreNodeService().getStoreInfoMeta().removeAll();
}
Copy link

Choose a reason for hiding this comment

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

Consider test isolation: Ensure that the tearDown method completely resets the system state. You might want to verify that all resources are properly cleaned up and consider adding additional cleanup operations if needed for complete test isolation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working size:S This PR changes 10-29 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant