Skip to content

refactor(scheduler): clean JVM shutdown for batch-style entry point#609

Merged
mkuchenbecker merged 2 commits into
mkuchenb/optimizer-4from
mkuchenb/optimizer-4.2
May 27, 2026
Merged

refactor(scheduler): clean JVM shutdown for batch-style entry point#609
mkuchenbecker merged 2 commits into
mkuchenb/optimizer-4from
mkuchenb/optimizer-4.2

Conversation

@mkuchenbecker
Copy link
Copy Markdown
Collaborator

Summary

Follow-up to PR #534 addressing reviewer feedback on the scheduler entry point.

The SchedulerApplication already used CommandLineRunner, but SpringApplication.run(...) left the context open after the runner finished — JPA pool / Spring framework threads (non-daemon) can keep the JVM alive, and the exit code does not reflect batch outcome. For a k8s cron-job-style batch app, that is the wrong shape.

Wraps SpringApplication.run in SpringApplication.exit + System.exit so the context is closed (@PreDestroy, JPA pool drain, etc.) and the JVM exits with a deterministic exit code after the CommandLineRunner completes. This is the standard Spring Boot batch-style entry point.

public static void main(String[] args) {
  System.exit(SpringApplication.exit(SpringApplication.run(SchedulerApplication.class, args)));
}

Scope

Only SchedulerApplication. AnalyzerApplication has the same shape and will be updated separately to keep this PR minimal and focused on the scheduler review thread.

Changes

  • Client-facing API Changes
  • Internal API Changes
  • Bug Fixes
  • New Features
  • Performance Improvements
  • Code Style
  • Refactoring
  • Documentation
  • Tests

Testing Done

  • ./gradlew :apps:optimizer:schedulerapp:build passes (compile + checkstyle + spotbugs).
  • Added new tests for the changes made.
  • Updated existing tests to reflect the changes made.
  • No tests added or updated. The change is a one-line wrapper around the standard Spring Boot startup; behavior under unit test (where the app is not booted) is unchanged.

Additional Information

  • Breaking Changes
  • Deprecations
  • Large PR broken into smaller PRs, and PR plan linked in the description.

mkuchenbecker and others added 2 commits May 27, 2026 14:35
Wrap SpringApplication.run in SpringApplication.exit + System.exit so the
context is closed (PreDestroy hooks, JPA pool drain, etc.) and the JVM
returns a deterministic exit code after the CommandLineRunner completes.
Matches the standard Spring Boot batch-style entry point and is what k8s
cron jobs need.

Analyzer left unchanged for now; will be applied separately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Apply the reviewer's full suggestion (#534): SchedulerApplication implements
CommandLineRunner + ExitCodeGenerator directly, wraps the work in try/catch,
tracks exitCode, and reports it via getExitCode(). SpringApplication.exit
propagates that to System.exit so the k8s CronJob pod status reflects batch
outcome. Removes the prior @bean CommandLineRunner.

Also adds spring.main.banner-mode=off per the suggestion.

Verified with the boot jar:
  - empty H2 schema (runner throws) -> caught, JPA pool drained, exit 1
  - schema preloaded, no PENDING ops -> exit 0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mkuchenbecker mkuchenbecker merged commit 10a5dda into mkuchenb/optimizer-4 May 27, 2026
@mkuchenbecker mkuchenbecker deleted the mkuchenb/optimizer-4.2 branch May 27, 2026 22:00
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.

1 participant