Check only the last execution when restarting a job instance - #5503
Open
jjh75607 wants to merge 2 commits into
Open
Check only the last execution when restarting a job instance#5503jjh75607 wants to merge 2 commits into
jjh75607 wants to merge 2 commits into
Conversation
Signed-off-by: jjh75607 <jjh7560734@gmail.com>
Resolve conflict with eec42cb (Fix inaccurate exception message in TaskExecutorJobLauncher). The message improvement is kept: the running JobExecution, not the JobInstance, is reported. The new TaskExecutorJobLauncherTests now stubs getLastJobExecution instead of getJobExecutions, which createJobExecution no longer calls. Signed-off-by: jjh75607 <jjh7560734@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves #5495
When a job instance is restarted,
TaskExecutorJobLauncher.createJobExecutionreads the instance history twice:getJobExecutions(jobInstance)for the running /UNKNOWN/COMPLETED/ABANDONEDchecks, thengetLastJobExecution(jobInstance)for the step checks and the execution context. SinceSimpleJobRepository extends SimpleJobExplorer, the first call hydrates every past execution with its job instance, step executions and both execution contexts, so the number of statements per launch grows with the number of past executions. Before 6.0 this check lived inSimpleJobRepositoryand went throughjobExecutionDao.findJobExecutions, which only loaded the job parameters per execution; moving it to the launcher in 90d8959 is where the slope went from one to eight statements per past execution.This change drops the first read and runs the status checks against the last execution only. A new execution is only created once these checks pass on the previous one, so on the launcher's own path the last execution is the only one that can be running,
UNKNOWNorCOMPLETED.Measured with the reproducer from #5495 (same instance restarted 12 times, statements counted with datasource-proxy on H2), on
mainbefore and after this change:What does change, and I want to be explicit about it: executions that are not the last one are no longer inspected. I built every combination of two past executions (8 statuses in each position) directly through
JobRepositoryand comparedmainwith this branch. The 35 cases where the older execution isFAILEDorSTOPPED, or where there is a single execution, behave identically, including the step status checks,preventRestart(), empty identifying parameters and carrying over the last execution context. The 6 cases where the older execution is running,COMPLETED,ABANDONEDorUNKNOWNwhile a newerFAILEDone exists were rejected onmainand now proceed. Such a history cannot be produced through the launcher; it takesabandonon an older execution after the instance has already been restarted, a directJobRepository.createJobExecutioncall, or two launches of the same instance racing past the check, which the existing code already only guards against probabilistically (see the comment abovejobRepository.createJobExecutionat the end of the method). If you would rather keep inspecting the full history, the alternative is a repository method that returns executions without hydrating them, which is an API addition I did not want to make on my own. Happy to go that way if you prefer.Tests added to
TaskExecutorJobOperatorTestsfor the last execution being running, being complete, and for a restart after several failed executions; these pass onmainas well and are there to pin the behaviour. Thespring-batch-core,spring-batch-integrationandspring-batch-testsuites pass. Also removes the now unusedjava.util.Listimport.Update (2026-08-28): merged
mainto resolve a conflict with eec42cb, which changed the running-execution message inside the loop this PR removes. The improved message is kept (lastJobExecutioninstead ofjobInstance), and the newTaskExecutorJobLauncherTestsnow stubsgetLastJobExecutioninstead ofgetJobExecutions, whichcreateJobExecutionno longer calls. Its assertions are unchanged.