Skip to content

fix(hotreload): Unset INSTANCE of executor on shutdown#324

Merged
chriswk merged 3 commits into
mainfrom
fix/springHotReload
Sep 9, 2025
Merged

fix(hotreload): Unset INSTANCE of executor on shutdown#324
chriswk merged 3 commits into
mainfrom
fix/springHotReload

Conversation

@chriswk
Copy link
Copy Markdown
Member

@chriswk chriswk commented Sep 8, 2025

fixes #315

Copy link
Copy Markdown
Contributor

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

This PR fixes issue #315 by ensuring the singleton INSTANCE of the scheduled executor is properly reset to null during shutdown, preventing stale references during hot reload scenarios.

Key changes:

  • Modified the setInterval method to return void instead of ScheduledFuture across all implementations
  • Added proper INSTANCE cleanup in shutdown methods to support hot reload scenarios
  • Enhanced logging for better debugging of executor lifecycle events

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
UnleashScheduledExecutor.java Updated interface to change setInterval return type and added shutdownNow method
UnleashScheduledExecutorImpl.java Implemented INSTANCE cleanup in shutdown methods and added logging
SynchronousTestExecutor.java Updated test implementation to match new interface signature

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +57 to +64
public void shutdown() {
this.scheduledThreadPoolExecutor.shutdown();
INSTANCE = null;
LOG.info("Shutdown - Scheduled Executor");
}

@Override
public void shutdownNow() {
Copy link

Copilot AI Sep 8, 2025

Choose a reason for hiding this comment

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

Setting INSTANCE to null in shutdown methods creates a race condition. If another thread calls getInstance() while shutdown is executing, it could create a new instance of an executor that's being shut down. Consider using proper synchronization or marking the instance as shutting down before nullifying it.

Suggested change
public void shutdown() {
this.scheduledThreadPoolExecutor.shutdown();
INSTANCE = null;
LOG.info("Shutdown - Scheduled Executor");
}
@Override
public void shutdownNow() {
public synchronized void shutdown() {
this.scheduledThreadPoolExecutor.shutdown();
INSTANCE = null;
LOG.info("Shutdown - Scheduled Executor");
}
@Override
public synchronized void shutdownNow() {

Copilot uses AI. Check for mistakes.
Comment on lines +57 to +64
public void shutdown() {
this.scheduledThreadPoolExecutor.shutdown();
INSTANCE = null;
LOG.info("Shutdown - Scheduled Executor");
}

@Override
public void shutdownNow() {
Copy link

Copilot AI Sep 8, 2025

Choose a reason for hiding this comment

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

Setting INSTANCE to null in shutdown methods creates a race condition. If another thread calls getInstance() while shutdown is executing, it could create a new instance of an executor that's being shut down. Consider using proper synchronization or marking the instance as shutting down before nullifying it.

Suggested change
public void shutdown() {
this.scheduledThreadPoolExecutor.shutdown();
INSTANCE = null;
LOG.info("Shutdown - Scheduled Executor");
}
@Override
public void shutdownNow() {
public synchronized void shutdown() {
this.scheduledThreadPoolExecutor.shutdown();
INSTANCE = null;
LOG.info("Shutdown - Scheduled Executor");
}
@Override
public synchronized void shutdownNow() {

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this makes sense

@coveralls
Copy link
Copy Markdown
Collaborator

coveralls commented Sep 8, 2025

Pull Request Test Coverage Report for Build 17575487826

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 6 of 6 (100.0%) changed or added relevant lines in 2 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.2%) to 79.472%

Totals Coverage Status
Change from base Build 16902971413: 0.2%
Covered Lines: 1229
Relevant Lines: 1510

💛 - Coveralls

Copy link
Copy Markdown
Contributor

@gastonfournier gastonfournier left a comment

Choose a reason for hiding this comment

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

I think this can work. I've added a small suggestion inline with Copilot suggestion: #325

@github-project-automation github-project-automation Bot moved this from New to Approved PRs in Issues and PRs Sep 8, 2025

public static synchronized UnleashScheduledExecutorImpl getInstance() {
if (INSTANCE == null) {
LOG.info("INSTANCE was null, rebuilding Scheduled Executor");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this be debug?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It shouldn't be here at all. I'll remove it before merging

private final ExecutorService executorService;

public UnleashScheduledExecutorImpl() {
LOG.info("Creating Scheduled executor");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this be debug? or be removed altogether

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Same, shouldn't be here. Added to verify behaviour during testing in example.

@chriswk chriswk merged commit 7dfe36a into main Sep 9, 2025
5 of 9 checks passed
@chriswk chriswk deleted the fix/springHotReload branch September 9, 2025 07:48
@github-project-automation github-project-automation Bot moved this from Approved PRs to Done in Issues and PRs Sep 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Unleash Client doesn't handle Spring Boot dev tools hot reloading

5 participants