Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make JobStep stoppable #4717

Open
andrianov17 opened this issue Nov 24, 2024 · 0 comments
Open

Make JobStep stoppable #4717

andrianov17 opened this issue Nov 24, 2024 · 0 comments
Labels
status: waiting-for-triage Issues that we did not analyse yet type: feature

Comments

@andrianov17
Copy link

andrianov17 commented Nov 24, 2024

We use JobStep-based implementation to call another job from a job, but unfortunately it doesn't support step.stop() at the moment when parent job stop request arrives via JobOperator.stop().

There are two moments which require adjustments:

  1. SimpleJobOperator
  2. JobStep along with nested job execution tracking

SimpleJobOperator:
It needs additional check in its stop() method as in:

@Override
public boolean stop(long executionId) throws NoSuchJobExecutionException, JobExecutionNotRunningException {
...
                                if (tasklet instanceof StoppableTasklet) {
                                    StepSynchronizationManager.register(stepExecution);
                                    ((StoppableTasklet)tasklet).stop(stepExecution);
                                    StepSynchronizationManager.release();
                                **} else if (step instanceof JobStep) {
                                    StepSynchronizationManager.register(stepExecution);
                                    ((JobStep) step).stop(stepExecution, this);
                                    StepSynchronizationManager.release();
                                }**
...

JobStep:
Currently, JobStep doesn't track its nested spawned job execution which would need to be stopped as per request above: ((JobStep) step).stop(stepExecution, this).

We achieve this via JobExecutionListener.beforeJob() and save just spawned job execution ID into parent job's step execution context (that's why, we needed stepExecution parameter above - to find nested job execution ID to be stopped by JobOperator).

JobStep stop() method could roughly look like this:
public void step(StepExecution stepExecution, JobOperator jobOperator) {
                // find spawned job execution from stepExecution (e.g., from its execution context)
                ...
                // This is preventive validation, otherwise, stop() will fail if job has been already completed
                // Validation below is taken from Spring Batch JobOperator.stop()
                JobExecution jobExecution = jobOperator.findExecutionById(childJobExecutionId);
                BatchStatus status = jobExecution.getStatus();
                if (!(status == BatchStatus.STARTED || status == BatchStatus.STARTING)) {
                    // Job is not running
                    LOGGER.warn("{} child job execution execution is not running - it cannot be stopped", childJobExecutionId);
                } else {
                    jobOperator.stop(childJobExecutionId);
                }
}

If similar behavior to track nested job execution ID is hard to implement in generic way, at least, the following default method could be introduced in JobStep:

default protected Long getChildExecutionId(StepExecution stepExecution) {
    return null;
}

In such a way JobStep could be inherited and the method defined accordingly.

Thank you in advance!

@andrianov17 andrianov17 added status: waiting-for-triage Issues that we did not analyse yet type: feature labels Nov 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: waiting-for-triage Issues that we did not analyse yet type: feature
Projects
None yet
Development

No branches or pull requests

1 participant