Skip to content

[Fix #1670] Stopping scheduledexecutorservice before clearing listeners - #1671

Merged
fjtirado merged 1 commit into
open-workflow-specification:mainfrom
fjtirado:Fix_#1670
Sep 11, 2026
Merged

[Fix #1670] Stopping scheduledexecutorservice before clearing listeners#1671
fjtirado merged 1 commit into
open-workflow-specification:mainfrom
fjtirado:Fix_#1670

Conversation

@fjtirado

@fjtirado fjtirado commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Fix #1670

@fjtirado
fjtirado marked this pull request as ready for review September 11, 2026 11:57
@fjtirado
fjtirado requested review from gmunozfe and a lite review from Copilot September 11, 2026 11:57

Copilot AI left a comment

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.

🟡 Changes recommended

One or more issues must be addressed before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR reorders application cleanup to stop scheduled execution before listeners are cleared, addressing shutdown-time concurrent modification errors.

Changes:

  • Adds shared executor shutdown logic.
  • Shuts down the scheduler before clearing listeners.
  • Reuses shutdown logic for the default executor factory.
File summaries
File Description
impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowUtils.java Updated as part of this pull request.
impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowApplication.java Updated as part of this pull request.
impl/core/src/main/java/io/serverlessworkflow/impl/DefaultExecutorServiceFactory.java Updated as part of this pull request.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 4
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowApplication.java Outdated
Comment thread impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowUtils.java Outdated
Copilot AI review requested due to automatic review settings September 11, 2026 12:44

Copilot AI left a comment

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.

🔵 Needs a closer look

One or more issues must be addressed before approval.

Review details

Suppressed comments (3)

impl/core/src/main/java/io/serverlessworkflow/impl/DefaultExecutorServiceFactory.java:31

  • safeShutdown uses shutdownNow(), so this change turns the factory's previous graceful shutdown() into an interrupting shutdown. This executor runs InMemoryEvents.publish and fork branches; closing the application can now abort in-flight work or discard queued work instead of allowing it to finish within the existing two-second wait. Keep this factory on a graceful shutdown path and use the forceful path only for the scheduler.
    WorkflowUtils.safeShutdown(service);

impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowApplication.java:589

  • ScheduledInstanceRunnable submits work through application.executorService() after running on this scheduler. Closing executorFactory first leaves a race where a scheduled callback reaches execute after that pool has been shut down, producing RejectedExecutionException; stop and await the scheduler before closing the executor factory.
    safeShutdown(schedulerExecutorService);

impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowUtils.java:183

  • shutdownNow() returns only tasks removed from the queue, not tasks already running. When the service has an active task but no queued tasks—which is common for this cached pool—this condition skips awaitTermination, so close() can clear listeners while the task is still publishing events. Always await after calling shutdownNow() (subject to the timeout).
    if (service != null && !service.isShutdown() && !service.shutdownNow().isEmpty()) {
  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 11, 2026 13:02

Copilot AI left a comment

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.

🟡 Changes recommended

One or more issues must be addressed before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

impl/core/src/main/java/io/serverlessworkflow/impl/DefaultExecutorServiceFactory.java:31

  • This changes the default application executor from the previous graceful shutdown() to shutdownNow(). That executor is also used for in-flight workflow execution and, when the default in-memory event consumer is created, event delivery; interrupting it can abort those operations rather than merely stopping future work. Keep the factory's graceful shutdown semantics and reserve the forceful helper for the scheduler, or make this policy explicit.
    WorkflowUtils.safeShutdown(service);
  • Files reviewed: 3/3 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowApplication.java Outdated
…ice before clearing listeners

Fix open-workflow-specification#1670

Signed-off-by: Francisco Javier Tirado Sarti <ftirados@ibm.com>
Copilot AI review requested due to automatic review settings September 11, 2026 13:31

Copilot AI left a comment

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.

🟡 Changes recommended

One or more issues must be addressed before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowApplication.java:589

  • The shared executor is shut down on the preceding line while the scheduled executor is still accepting work. A scheduled task can race this call and ScheduledInstanceRunnable then submits the workflow through application().executorService().execute(...), which now throws RejectedExecutionException. The close sequence needs to stop/drain scheduled submissions and coordinate completion callbacks before shutting down the shared executor.
    safeShutdown(schedulerExecutorService);
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Lite

@gmunozfe gmunozfe left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks good to me, well done @fjtirado

@fjtirado
fjtirado merged commit d1559d7 into open-workflow-specification:main Sep 11, 2026
3 checks passed
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.

Potential concurrent exception when closing the application

3 participants